From 77ac4129762eb4ff1c2b63e2b6c99f04dbb32f19 Mon Sep 17 00:00:00 2001 From: Jianmin Date: Thu, 5 Dec 2024 09:34:09 +0800 Subject: [PATCH 1/3] Rebuild to fix CVE-2023-24534 CVE-2023-24536 CVE-2023-24537 CVE-2023-24538 CVE-2023-29406 CVE-2022-41715 CVE-2024-24791 CVE-2021-34558 and CVE-2022-1962 (cherry picked from commit 7f01aab282fe32043b58724729e39361bf0cb6d3) --- buildah.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/buildah.spec b/buildah.spec index 5f8eb5d..c8f1e7a 100644 --- a/buildah.spec +++ b/buildah.spec @@ -25,13 +25,13 @@ Name: buildah Version: 1.26.1 -Release: 1 +Release: 2 Summary: A command line tool used for creating OCI Images License: ASL 2.0 and BSD and MIT and MPLv2.0 URL: https://%{name}.io Source: %{git0}/archive/v%{version}.tar.gz Source1: https://github.com/cpuguy83/go-md2man/archive/v1.0.10.tar.gz -BuildRequires: device-mapper-devel git-core golang >= 1.16.6 glib2-devel glibc-static gpgme-devel libassuan-devel +BuildRequires: device-mapper-devel git-core golang >= 1.17.3-33 glib2-devel glibc-static gpgme-devel libassuan-devel BuildRequires: make ostree-devel btrfs-progs-devel libseccomp-static Requires: containers-common netavark iptables nftables libseccomp >= 2.4.1-0 Suggests: containernetworking-plugins >= 0.9.1-1 cpp qemu-user-static @@ -136,5 +136,8 @@ make DESTDIR=%{buildroot} PREFIX=%{_prefix} -C docs install %{_datadir}/bash-completion/completions/%{name} %changelog +* Thu Dec 19 2024 Jianmin - 1.26.1-2 +- Rebuild on Go 1.17.3-33 to fix CVE-2023-24534 CVE-2023-24536 CVE-2023-24537 CVE-2023-24538 CVE-2023-29406 CVE-2022-41715 CVE-2024-24791 CVE-2021-34558 and CVE-2022-1962 + * Mon Jun 20 2022 fushanqing - 1.26.1-1 - Initial package -- Gitee From 9766b6d4928b9e01e62d7989873e4faa9a89d75e Mon Sep 17 00:00:00 2001 From: Jianmin Date: Wed, 8 Jan 2025 20:45:09 +0800 Subject: [PATCH 2/3] fix CVE-2023-39325 CVE-2022-41723 and CVE-2023-48795 (cherry picked from commit 2860284f091a01e861fcd4dc5b8e961c1ea18ef5) --- 0001-CVE-2023-39325.patch | 117 ++++++++++++++++++ 0002-CVE-2023-48795.patch | 245 ++++++++++++++++++++++++++++++++++++++ 0003-CVE-2022-41723.patch | 158 ++++++++++++++++++++++++ buildah.spec | 8 +- 4 files changed, 527 insertions(+), 1 deletion(-) create mode 100644 0001-CVE-2023-39325.patch create mode 100644 0002-CVE-2023-48795.patch create mode 100644 0003-CVE-2022-41723.patch diff --git a/0001-CVE-2023-39325.patch b/0001-CVE-2023-39325.patch new file mode 100644 index 0000000..86d698a --- /dev/null +++ b/0001-CVE-2023-39325.patch @@ -0,0 +1,117 @@ +diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go +index e644d9b..7575bc5 100644 +--- a/vendor/golang.org/x/net/http2/server.go ++++ b/vendor/golang.org/x/net/http2/server.go +@@ -520,9 +520,11 @@ type serverConn struct { + advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client + curClientStreams uint32 // number of open streams initiated by the client + curPushedStreams uint32 // number of open streams initiated by server push ++ curHandlers uint32 // number of running handler goroutines + maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests + maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes + streams map[uint32]*stream ++ unstartedHandlers []unstartedHandler + initialStreamSendWindowSize int32 + maxFrameSize int32 + headerTableSize uint32 +@@ -909,6 +911,8 @@ func (sc *serverConn) serve() { + return + case gracefulShutdownMsg: + sc.startGracefulShutdownInternal() ++ case handlerDoneMsg: ++ sc.handlerDone() + default: + panic("unknown timer") + } +@@ -954,6 +958,7 @@ var ( + idleTimerMsg = new(serverMessage) + shutdownTimerMsg = new(serverMessage) + gracefulShutdownMsg = new(serverMessage) ++ handlerDoneMsg = new(serverMessage) + ) + + func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) } +@@ -1911,8 +1916,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error { + sc.conn.SetReadDeadline(time.Time{}) + } + +- go sc.runHandler(rw, req, handler) +- return nil ++ return sc.scheduleHandler(id, rw, req, handler) + } + + func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error { +@@ -2159,8 +2163,62 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r + return rw, req, nil + } + ++type unstartedHandler struct { ++ streamID uint32 ++ rw *responseWriter ++ req *http.Request ++ handler func(http.ResponseWriter, *http.Request) ++} ++ ++// scheduleHandler starts a handler goroutine, ++// or schedules one to start as soon as an existing handler finishes. ++func (sc *serverConn) scheduleHandler(streamID uint32, rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) error { ++ sc.serveG.check() ++ maxHandlers := sc.advMaxStreams ++ if sc.curHandlers < maxHandlers { ++ sc.curHandlers++ ++ go sc.runHandler(rw, req, handler) ++ return nil ++ } ++ if len(sc.unstartedHandlers) > int(4*sc.advMaxStreams) { ++ return sc.countError("too_many_early_resets", ConnectionError(ErrCodeEnhanceYourCalm)) ++ } ++ sc.unstartedHandlers = append(sc.unstartedHandlers, unstartedHandler{ ++ streamID: streamID, ++ rw: rw, ++ req: req, ++ handler: handler, ++ }) ++ return nil ++} ++ ++func (sc *serverConn) handlerDone() { ++ sc.serveG.check() ++ sc.curHandlers-- ++ i := 0 ++ maxHandlers := sc.advMaxStreams ++ for ; i < len(sc.unstartedHandlers); i++ { ++ u := sc.unstartedHandlers[i] ++ if sc.streams[u.streamID] == nil { ++ // This stream was reset before its goroutine had a chance to start. ++ continue ++ } ++ if sc.curHandlers >= maxHandlers { ++ break ++ } ++ sc.curHandlers++ ++ go sc.runHandler(u.rw, u.req, u.handler) ++ sc.unstartedHandlers[i] = unstartedHandler{} // don't retain references ++ } ++ sc.unstartedHandlers = sc.unstartedHandlers[i:] ++ if len(sc.unstartedHandlers) == 0 { ++ sc.unstartedHandlers = nil ++ } ++} ++ + // Run on its own goroutine. + func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) { ++ defer sc.sendServeMsg(handlerDoneMsg) + didPanic := true + defer func() { + rw.rws.stream.cancelCtx() +@@ -2923,6 +2982,10 @@ func (sc *serverConn) startPush(msg *startPushRequest) { + panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err)) + } + ++ // This is the first request on the connection, ++ // so start the handler directly rather than going ++ // through scheduleHandler. ++ sc.curHandlers++ + go sc.runHandler(rw, req, sc.handler.ServeHTTP) + return promisedID, nil + } diff --git a/0002-CVE-2023-48795.patch b/0002-CVE-2023-48795.patch new file mode 100644 index 0000000..c836580 --- /dev/null +++ b/0002-CVE-2023-48795.patch @@ -0,0 +1,245 @@ +From 409a35189b23ca1490265c4eeb13ea370d3144ba Mon Sep 17 00:00:00 2001 +From: Jianmin +Date: Mon, 23 Dec 2024 17:47:26 +0800 +Subject: [PATCH] [backport] ssh: implement strict KEX protocol changes + +--- + vendor/golang.org/x/crypto/ssh/handshake.go | 59 +++++++++++++++++++-- + vendor/golang.org/x/crypto/ssh/transport.go | 32 +++++++++-- + 2 files changed, 81 insertions(+), 10 deletions(-) + +diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go +index 653dc4d..e7d4545 100644 +--- a/vendor/golang.org/x/crypto/ssh/handshake.go ++++ b/vendor/golang.org/x/crypto/ssh/handshake.go +@@ -34,6 +34,16 @@ type keyingTransport interface { + // direction will be effected if a msgNewKeys message is sent + // or received. + prepareKeyChange(*algorithms, *kexResult) error ++ ++ // setStrictMode sets the strict KEX mode, notably triggering ++ // sequence number resets on sending or receiving msgNewKeys. ++ // If the sequence number is already > 1 when setStrictMode ++ // is called, an error is returned. ++ setStrictMode() error ++ ++ // setInitialKEXDone indicates to the transport that the initial key exchange ++ // was completed ++ setInitialKEXDone() + } + + // handshakeTransport implements rekeying on top of a keyingTransport +@@ -94,6 +104,10 @@ type handshakeTransport struct { + + // The session ID or nil if first kex did not complete yet. + sessionID []byte ++ ++ // strictMode indicates if the other side of the handshake indicated ++ // that we should be following the strict KEX protocol restrictions. ++ strictMode bool + } + + type pendingKex struct { +@@ -201,7 +215,10 @@ func (t *handshakeTransport) readLoop() { + close(t.incoming) + break + } +- if p[0] == msgIgnore || p[0] == msgDebug { ++ // If this is the first kex, and strict KEX mode is enabled, ++ // we don't ignore any messages, as they may be used to manipulate ++ // the packet sequence numbers. ++ if !(t.sessionID == nil && t.strictMode) && (p[0] == msgIgnore || p[0] == msgDebug) { + continue + } + t.incoming <- p +@@ -432,6 +449,11 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) { + return successPacket, nil + } + ++const ( ++ kexStrictClient = "kex-strict-c-v00@openssh.com" ++ kexStrictServer = "kex-strict-s-v00@openssh.com" ++) ++ + // sendKexInit sends a key change message. + func (t *handshakeTransport) sendKexInit() error { + t.mu.Lock() +@@ -445,7 +467,6 @@ func (t *handshakeTransport) sendKexInit() error { + } + + msg := &kexInitMsg{ +- KexAlgos: t.config.KeyExchanges, + CiphersClientServer: t.config.Ciphers, + CiphersServerClient: t.config.Ciphers, + MACsClientServer: t.config.MACs, +@@ -455,6 +476,13 @@ func (t *handshakeTransport) sendKexInit() error { + } + io.ReadFull(rand.Reader, msg.Cookie[:]) + ++ // We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm, ++ // and possibly to add the ext-info extension algorithm. Since the slice may be the ++ // user owned KeyExchanges, we create our own slice in order to avoid using user ++ // owned memory by mistake. ++ msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+2) // room for kex-strict and ext-info ++ msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...) ++ + isServer := len(t.hostKeys) > 0 + if isServer { + for _, k := range t.hostKeys { +@@ -474,17 +502,24 @@ func (t *handshakeTransport) sendKexInit() error { + msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat) + } + } ++ ++ if t.sessionID == nil { ++ msg.KexAlgos = append(msg.KexAlgos, kexStrictServer) ++ } + } else { + msg.ServerHostKeyAlgos = t.hostKeyAlgorithms + + // As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what + // algorithms the server supports for public key authentication. See RFC + // 8308, Section 2.1. ++ // ++ // We also send the strict KEX mode extension algorithm, in order to opt ++ // into the strict KEX mode. + if firstKeyExchange := t.sessionID == nil; firstKeyExchange { +- msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1) +- msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...) + msg.KexAlgos = append(msg.KexAlgos, "ext-info-c") ++ msg.KexAlgos = append(msg.KexAlgos, kexStrictClient) + } ++ + } + + packet := Marshal(msg) +@@ -581,6 +616,13 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { + return err + } + ++ if t.sessionID == nil && ((isClient && contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && contains(clientInit.KexAlgos, kexStrictClient))) { ++ t.strictMode = true ++ if err := t.conn.setStrictMode(); err != nil { ++ return err ++ } ++ } ++ + // We don't send FirstKexFollows, but we handle receiving it. + // + // RFC 4253 section 7 defines the kex and the agreement method for +@@ -615,7 +657,8 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { + return err + } + +- if t.sessionID == nil { ++ firstKeyExchange := t.sessionID == nil ++ if firstKeyExchange { + t.sessionID = result.H + } + result.SessionID = t.sessionID +@@ -632,6 +675,12 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { + return unexpectedMessageError(msgNewKeys, packet[0]) + } + ++ if firstKeyExchange { ++ // Indicates to the transport that the first key exchange is completed ++ // after receiving SSH_MSG_NEWKEYS. ++ t.conn.setInitialKEXDone() ++ } ++ + return nil + } + +diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go +index acf5a21..4df45fc 100644 +--- a/vendor/golang.org/x/crypto/ssh/transport.go ++++ b/vendor/golang.org/x/crypto/ssh/transport.go +@@ -48,6 +48,9 @@ type transport struct { + rand io.Reader + isClient bool + io.Closer ++ ++ strictMode bool ++ initialKEXDone bool + } + + // packetCipher represents a combination of SSH encryption/MAC +@@ -73,6 +76,18 @@ type connectionState struct { + pendingKeyChange chan packetCipher + } + ++func (t *transport) setStrictMode() error { ++ if t.reader.seqNum != 1 { ++ return errors.New("ssh: sequence number != 1 when strict KEX mode requested") ++ } ++ t.strictMode = true ++ return nil ++} ++ ++func (t *transport) setInitialKEXDone() { ++ t.initialKEXDone = true ++} ++ + // prepareKeyChange sets up key material for a keychange. The key changes in + // both directions are triggered by reading and writing a msgNewKey packet + // respectively. +@@ -111,11 +126,12 @@ func (t *transport) printPacket(p []byte, write bool) { + // Read and decrypt next packet. + func (t *transport) readPacket() (p []byte, err error) { + for { +- p, err = t.reader.readPacket(t.bufReader) ++ p, err = t.reader.readPacket(t.bufReader, t.strictMode) + if err != nil { + break + } +- if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) { ++ // in strict mode we pass through DEBUG and IGNORE packets only during the initial KEX ++ if len(p) == 0 || (t.strictMode && !t.initialKEXDone) || (p[0] != msgIgnore && p[0] != msgDebug) { + break + } + } +@@ -126,7 +142,7 @@ func (t *transport) readPacket() (p []byte, err error) { + return p, err + } + +-func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { ++func (s *connectionState) readPacket(r *bufio.Reader, strictMode bool) ([]byte, error) { + packet, err := s.packetCipher.readCipherPacket(s.seqNum, r) + s.seqNum++ + if err == nil && len(packet) == 0 { +@@ -139,6 +155,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { + select { + case cipher := <-s.pendingKeyChange: + s.packetCipher = cipher ++ if strictMode { ++ s.seqNum = 0 ++ } + default: + return nil, errors.New("ssh: got bogus newkeys message") + } +@@ -169,10 +188,10 @@ func (t *transport) writePacket(packet []byte) error { + if debugTransport { + t.printPacket(packet, true) + } +- return t.writer.writePacket(t.bufWriter, t.rand, packet) ++ return t.writer.writePacket(t.bufWriter, t.rand, packet, t.strictMode) + } + +-func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { ++func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte, strictMode bool) error { + changeKeys := len(packet) > 0 && packet[0] == msgNewKeys + + err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet) +@@ -187,6 +206,9 @@ func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet [] + select { + case cipher := <-s.pendingKeyChange: + s.packetCipher = cipher ++ if strictMode { ++ s.seqNum = 0 ++ } + default: + panic("ssh: no key material for msgNewKeys") + } +-- +2.39.5 (Apple Git-154) + diff --git a/0003-CVE-2022-41723.patch b/0003-CVE-2022-41723.patch new file mode 100644 index 0000000..f225114 --- /dev/null +++ b/0003-CVE-2022-41723.patch @@ -0,0 +1,158 @@ +From 11bc24fcd1f15f54849c7aebefe1bbdc0d75437b Mon Sep 17 00:00:00 2001 +From: bwzhang +Date: Sun, 7 Apr 2024 17:04:42 +0800 +Subject: [PATCH] fix CVE-2022-41723 + +http2/hpack: avoid quadratic complexity in hpack decoding + +When parsing a field literal containing two Huffman-encoded strings, +don't decode the first string until verifying all data is present. +Avoids forced quadratic complexity when repeatedly parsing a partial +field, repeating the Huffman decoding of the string on each iteration. + +Thanks to Philippe Antoine (Catena cyber) for reporting this issue. + +Fixes golang/go#57855 +Fixes CVE-2022-41723 + +Change-Id: I58a743df450a4a4923dddd5cf6bb0592b0a7bdf3 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1688184 +TryBot-Result: Security TryBots +Reviewed-by: Julie Qiu +Run-TryBot: Damien Neil +Reviewed-by: Roland Shoemaker +Reviewed-on: https://go-review.googlesource.com/c/net/+/468135 +Run-TryBot: Michael Pratt +Reviewed-by: Roland Shoemaker +Reviewed-by: Than McIntosh +Auto-Submit: Michael Pratt +TryBot-Result: Gopher Robot +--- + vendor/golang.org/x/net/http2/hpack/hpack.go | 79 ++++++++++++-------- + 1 file changed, 49 insertions(+), 30 deletions(-) + +diff --git a/vendor/golang.org/x/net/http2/hpack/hpack.go b/vendor/golang.org/x/net/http2/hpack/hpack.go +index 85f18a2..7e7e4cf 100644 +--- a/vendor/golang.org/x/net/http2/hpack/hpack.go ++++ b/vendor/golang.org/x/net/http2/hpack/hpack.go +@@ -359,6 +359,7 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error { + + var hf HeaderField + wantStr := d.emitEnabled || it.indexed() ++ var undecodedName undecodedString + if nameIdx > 0 { + ihf, ok := d.at(nameIdx) + if !ok { +@@ -366,15 +367,27 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error { + } + hf.Name = ihf.Name + } else { +- hf.Name, buf, err = d.readString(buf, wantStr) ++ undecodedName, buf, err = d.readString(buf) + if err != nil { + return err + } + } +- hf.Value, buf, err = d.readString(buf, wantStr) ++ undecodedValue, buf, err := d.readString(buf) + if err != nil { + return err + } ++ if wantStr { ++ if nameIdx <= 0 { ++ hf.Name, err = d.decodeString(undecodedName) ++ if err != nil { ++ return err ++ } ++ } ++ hf.Value, err = d.decodeString(undecodedValue) ++ if err != nil { ++ return err ++ } ++ } + d.buf = buf + if it.indexed() { + d.dynTab.add(hf) +@@ -459,46 +472,52 @@ func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) { + return 0, origP, errNeedMore + } + +-// readString decodes an hpack string from p. ++// readString reads an hpack string from p. + // +-// wantStr is whether s will be used. If false, decompression and +-// []byte->string garbage are skipped if s will be ignored +-// anyway. This does mean that huffman decoding errors for non-indexed +-// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server +-// is returning an error anyway, and because they're not indexed, the error +-// won't affect the decoding state. +-func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) { ++// It returns a reference to the encoded string data to permit deferring decode costs ++// until after the caller verifies all data is present. ++func (d *Decoder) readString(p []byte) (u undecodedString, remain []byte, err error) { + if len(p) == 0 { +- return "", p, errNeedMore ++ return u, p, errNeedMore + } + isHuff := p[0]&128 != 0 + strLen, p, err := readVarInt(7, p) + if err != nil { +- return "", p, err ++ return u, p, err + } + if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) { +- return "", nil, ErrStringLength ++ // Returning an error here means Huffman decoding errors ++ // for non-indexed strings past the maximum string length ++ // are ignored, but the server is returning an error anyway ++ // and because the string is not indexed the error will not ++ // affect the decoding state. ++ return u, nil, ErrStringLength + } + if uint64(len(p)) < strLen { +- return "", p, errNeedMore +- } +- if !isHuff { +- if wantStr { +- s = string(p[:strLen]) +- } +- return s, p[strLen:], nil ++ return u, p, errNeedMore + } ++ u.isHuff = isHuff ++ u.b = p[:strLen] ++ return u, p[strLen:], nil ++} + +- if wantStr { +- buf := bufPool.Get().(*bytes.Buffer) +- buf.Reset() // don't trust others +- defer bufPool.Put(buf) +- if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil { +- buf.Reset() +- return "", nil, err +- } ++type undecodedString struct { ++ isHuff bool ++ b []byte ++} ++ ++func (d *Decoder) decodeString(u undecodedString) (string, error) { ++ if !u.isHuff { ++ return string(u.b), nil ++ } ++ buf := bufPool.Get().(*bytes.Buffer) ++ buf.Reset() // don't trust others ++ var s string ++ err := huffmanDecode(buf, d.maxStrLen, u.b) ++ if err == nil { + s = buf.String() +- buf.Reset() // be nice to GC + } +- return s, p[strLen:], nil ++ buf.Reset() // be nice to GC ++ bufPool.Put(buf) ++ return s, err + } +-- +2.20.1 diff --git a/buildah.spec b/buildah.spec index c8f1e7a..515d36b 100644 --- a/buildah.spec +++ b/buildah.spec @@ -25,12 +25,15 @@ Name: buildah Version: 1.26.1 -Release: 2 +Release: 3 Summary: A command line tool used for creating OCI Images License: ASL 2.0 and BSD and MIT and MPLv2.0 URL: https://%{name}.io Source: %{git0}/archive/v%{version}.tar.gz Source1: https://github.com/cpuguy83/go-md2man/archive/v1.0.10.tar.gz +Patch1: 0001-CVE-2023-39325.patch +Patch2: 0002-CVE-2023-48795.patch +Patch3: 0003-CVE-2022-41723.patch BuildRequires: device-mapper-devel git-core golang >= 1.17.3-33 glib2-devel glibc-static gpgme-devel libassuan-devel BuildRequires: make ostree-devel btrfs-progs-devel libseccomp-static Requires: containers-common netavark iptables nftables libseccomp >= 2.4.1-0 @@ -136,6 +139,9 @@ make DESTDIR=%{buildroot} PREFIX=%{_prefix} -C docs install %{_datadir}/bash-completion/completions/%{name} %changelog +* Mon Dec 23 2024 Jianmin - 1.26.1-3 +- fix CVE-2023-39325, CVE-2022-41723 and CVE-2023-48795 + * Thu Dec 19 2024 Jianmin - 1.26.1-2 - Rebuild on Go 1.17.3-33 to fix CVE-2023-24534 CVE-2023-24536 CVE-2023-24537 CVE-2023-24538 CVE-2023-29406 CVE-2022-41715 CVE-2024-24791 CVE-2021-34558 and CVE-2022-1962 -- Gitee From 683c1fc3ca2c8a2a0b60a3b6cdd0b160e560970c Mon Sep 17 00:00:00 2001 From: Jianmin Date: Wed, 25 Dec 2024 11:38:29 +0800 Subject: [PATCH 3/3] fix CVE-2024-1753 and CVE-2022-2990 (cherry picked from commit 0b266a05625d1dd9555fb24e45403c0cdcae7f21) --- 0004-CVE-2024-1753.patch | 70 +++++++++++++++++++++++++++++++ 0005-CVE-2022-2990.patch | 89 ++++++++++++++++++++++++++++++++++++++++ buildah.spec | 7 +++- 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 0004-CVE-2024-1753.patch create mode 100644 0005-CVE-2022-2990.patch diff --git a/0004-CVE-2024-1753.patch b/0004-CVE-2024-1753.patch new file mode 100644 index 0000000..1d36ee6 --- /dev/null +++ b/0004-CVE-2024-1753.patch @@ -0,0 +1,70 @@ +From 8c261ed7492513d90a22448ef58981b4175f67d2 Mon Sep 17 00:00:00 2001 +From: tomsweeneyredhat +Date: Mon, 18 Mar 2024 10:47:43 -0400 +Subject: [PATCH] [release-1.26] CVE-2024-1753 container escape fix + +Addresses CVE-2024-1753 which allowed a user to write files to the +`/` directory of the host machine if selinux was not enabled. + +Signed-off-by: tomsweeneyredhat +--- + internal/parse/parse.go | 7 ++++++- + tests/bud.bats | 23 +++++++++++++++++++++++ + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/internal/parse/parse.go b/internal/parse/parse.go +index 1c736cdf11f..6610de0c91e 100644 +--- a/internal/parse/parse.go ++++ b/internal/parse/parse.go +@@ -8,6 +8,7 @@ import ( + "strconv" + "strings" + ++ "github.com/containers/buildah/copier" + "github.com/containers/buildah/internal" + internalUtil "github.com/containers/buildah/internal/util" + "github.com/containers/common/pkg/parse" +@@ -151,7 +152,11 @@ func GetBindMount(ctx *types.SystemContext, args []string, contextDir string, st + // buildkit parity: support absolute path for sources from current build context + if contextDir != "" { + // path should be /contextDir/specified path +- newMount.Source = filepath.Join(contextDir, filepath.Clean(string(filepath.Separator)+newMount.Source)) ++ evaluated, err := copier.Eval(contextDir, newMount.Source, copier.EvalOptions{}) ++ if err != nil { ++ return newMount, "", err ++ } ++ newMount.Source = evaluated + } else { + // looks like its coming from `build run --mount=type=bind` allow using absolute path + // error out if no source is set +diff --git a/tests/bud.bats b/tests/bud.bats +index e4b16b1ac0d..c016e451137 100644 +--- a/tests/bud.bats ++++ b/tests/bud.bats +@@ -4598,3 +4598,26 @@ _EOF + echo checking: + ! grep 'not fully killed' ${TEST_SCRATCH_DIR}/log + } ++ ++@test "build no write file on host - CVE-2024-1753" { ++ _prefetch alpine ++ cat > ${TEST_SCRATCH_DIR}/Containerfile << _EOF ++FROM alpine as base ++ ++RUN ln -s / /rootdir ++ ++FROM alpine ++ ++RUN echo "With exploit show host root, not the container's root, and create /BIND_BREAKOUT in / on the host" ++RUN --mount=type=bind,from=base,source=/rootdir,destination=/exploit,rw ls -l /exploit; touch /exploit/BIND_BREAKOUT; ls -l /exploit ++ ++_EOF ++ ++ run_buildah build $WITH_POLICY_JSON ${TEST_SCRATCH_DIR} ++ expect_output --substring "/BIND_BREAKOUT" ++ ++ run ls /BIND_BREAKOUT ++ rm -f /BIND_BREAKOUT ++ assert "$status" -eq 2 "exit code from ls" ++ expect_output --substring "No such file or directory" ++} diff --git a/0005-CVE-2022-2990.patch b/0005-CVE-2022-2990.patch new file mode 100644 index 0000000..b8bcb95 --- /dev/null +++ b/0005-CVE-2022-2990.patch @@ -0,0 +1,89 @@ +From a9c5cbc1e66e6ac8e5fc6749755c1b40690ffc23 Mon Sep 17 00:00:00 2001 +From: Jianmin +Date: Wed, 25 Dec 2024 12:49:25 +0800 +Subject: [PATCH] [backport][PATCH] run: add container gid to additional groups + +--- + run_linux.go | 1 + + tests/bud.bats | 16 ++++++++++++++++ + tests/bud/supplemental-groups/Dockerfile | 3 +++ + tests/run.bats | 14 ++++++++++++++ + 4 files changed, 34 insertions(+) + create mode 100644 tests/bud/supplemental-groups/Dockerfile + +diff --git a/run_linux.go b/run_linux.go +index f52754c..7a61a9a 100644 +--- a/run_linux.go ++++ b/run_linux.go +@@ -2063,6 +2063,7 @@ func (b *Builder) configureUIDGID(g *generate.Generator, mountPoint string, opti + } + g.SetProcessUID(user.UID) + g.SetProcessGID(user.GID) ++ g.AddProcessAdditionalGid(user.GID) + for _, gid := range user.AdditionalGids { + g.AddProcessAdditionalGid(gid) + } +diff --git a/tests/bud.bats b/tests/bud.bats +index f43a4a9..8d2ca2c 100644 +--- a/tests/bud.bats ++++ b/tests/bud.bats +@@ -601,6 +601,22 @@ _EOF + expect_output "[]" + } + ++@test "build test has gid in supplemental groups" { ++ _prefetch alpine ++ run_buildah build $WITH_POLICY_JSON -t source -f $BUDFILES/supplemental-groups/Dockerfile ++ # gid 1000 must be in supplemental groups ++ expect_output --substring "Groups: 1000" ++} ++ ++@test "build test if supplemental groups has gid with --isolation chroot" { ++ test -z "${BUILDAH_ISOLATION}" || skip "BUILDAH_ISOLATION=${BUILDAH_ISOLATION} overrides --isolation" ++ ++ _prefetch alpine ++ run_buildah build --isolation chroot $WITH_POLICY_JSON -t source -f $BUDFILES/supplemental-groups/Dockerfile ++ # gid 1000 must be in supplemental groups ++ expect_output --substring "Groups: 1000" ++} ++ + @test "build with custom build output and output rootfs to directory" { + _prefetch alpine + mytmpdir=${TEST_SCRATCH_DIR}/my-dir +diff --git a/tests/bud/supplemental-groups/Dockerfile b/tests/bud/supplemental-groups/Dockerfile +new file mode 100644 +index 0000000..462d9ea +--- /dev/null ++++ b/tests/bud/supplemental-groups/Dockerfile +@@ -0,0 +1,3 @@ ++FROM alpine ++USER 1000:1000 ++RUN cat /proc/$$/status +diff --git a/tests/run.bats b/tests/run.bats +index 6574337..6a7cadf 100644 +--- a/tests/run.bats ++++ b/tests/run.bats +@@ -349,6 +349,20 @@ function configure_and_check_user() { + expect_output "888:888" + } + ++@test "run --user and verify gid in supplemental groups" { ++ skip_if_no_runtime ++ ++ # Create the container. ++ _prefetch alpine ++ run_buildah from $WITH_POLICY_JSON alpine ++ ctr="$output" ++ ++ # Run with uid:gid 1000:1000 and verify if gid is present in additional groups ++ run_buildah run --user 1000:1000 "$ctr" cat /proc/self/status ++ # gid 1000 must be in additional/supplemental groups ++ expect_output --substring "Groups: 1000 " ++} ++ + @test "run --workingdir" { + skip_if_no_runtime + +-- +2.39.5 (Apple Git-154) + diff --git a/buildah.spec b/buildah.spec index 515d36b..773a262 100644 --- a/buildah.spec +++ b/buildah.spec @@ -25,7 +25,7 @@ Name: buildah Version: 1.26.1 -Release: 3 +Release: 4 Summary: A command line tool used for creating OCI Images License: ASL 2.0 and BSD and MIT and MPLv2.0 URL: https://%{name}.io @@ -34,6 +34,8 @@ Source1: https://github.com/cpuguy83/go-md2man/archive/v1.0.10.tar.gz Patch1: 0001-CVE-2023-39325.patch Patch2: 0002-CVE-2023-48795.patch Patch3: 0003-CVE-2022-41723.patch +Patch4: 0004-CVE-2024-1753.patch +Patch5: 0005-CVE-2022-2990.patch BuildRequires: device-mapper-devel git-core golang >= 1.17.3-33 glib2-devel glibc-static gpgme-devel libassuan-devel BuildRequires: make ostree-devel btrfs-progs-devel libseccomp-static Requires: containers-common netavark iptables nftables libseccomp >= 2.4.1-0 @@ -139,6 +141,9 @@ make DESTDIR=%{buildroot} PREFIX=%{_prefix} -C docs install %{_datadir}/bash-completion/completions/%{name} %changelog +* Wed Dec 25 2024 Jianmin - 1.26.1-4 +- fix CVE-2024-1753 and CVE-2022-2990 + * Mon Dec 23 2024 Jianmin - 1.26.1-3 - fix CVE-2023-39325, CVE-2022-41723 and CVE-2023-48795 -- Gitee