From 6c0ec49994e9a0fcf56f76cbfb20df6b80d6f2df Mon Sep 17 00:00:00 2001 From: huzhangying Date: Tue, 11 Nov 2025 19:45:21 +0800 Subject: [PATCH] [backport]fix CVE-2025-58183,CVE-2025-58185,CVE-2025-58189,CVE-2025-61724 --- ...58183-archive-tar-set-a-limit-on-the.patch | 90 ++++++++++ ...-crypto-tls-quote-protocols-incrypto.patch | 44 +++++ ...-61724-net-textproto-avoid-quadratic.patch | 70 ++++++++ ...oding-asn1-prevent-memory-exhaustion.patch | 166 ++++++++++++++++++ golang.spec | 12 +- 5 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 0079-CVE-2025-58183-archive-tar-set-a-limit-on-the.patch create mode 100644 0080-CVE-2025-58189-crypto-tls-quote-protocols-incrypto.patch create mode 100644 0081-CVE-2025-61724-net-textproto-avoid-quadratic.patch create mode 100644 0082-CVE-2025-58185-encoding-asn1-prevent-memory-exhaustion.patch diff --git a/0079-CVE-2025-58183-archive-tar-set-a-limit-on-the.patch b/0079-CVE-2025-58183-archive-tar-set-a-limit-on-the.patch new file mode 100644 index 0000000..83779aa --- /dev/null +++ b/0079-CVE-2025-58183-archive-tar-set-a-limit-on-the.patch @@ -0,0 +1,90 @@ +From f7a68d3804efabd271f0338391858bc1e7e57422 Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Thu, 11 Sep 2025 13:32:10 -0700 +Subject: [PATCH] archive/tar: set a limit on the size of GNU + sparse file 1.0 regions + +Sparse files in tar archives contain only the non-zero components +of the file. There are several different encodings for sparse +files. When reading GNU tar pax 1.0 sparse files, archive/tar did +not set a limit on the size of the sparse region data. A malicious +archive containing a large number of sparse blocks could cause +archive/tar to read an unbounded amount of data from the archive +into memory. + +Reference: https://go-review.googlesource.com/c/go/+/709861 +Conflict: no + +Since a malicious input can be highly compressable, a small +compressed input could cause very large allocations. + +Cap the size of the sparse block data to the same limit used +for PAX headers (1 MiB). + +Thanks to Harshit Gupta (Mr HAX) (https://www.linkedin.com/in/iam-harshit-gupta/) +for reporting this issue. + +Fixes CVE-2025-58183 +Fixes #75677 + +Change-Id: I70b907b584a7b8676df8a149a1db728ae681a770 +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2800 +Reviewed-by: Roland Shoemaker +Reviewed-by: Nicholas Husin +Reviewed-on: https://go-review.googlesource.com/c/go/+/709861 +Auto-Submit: Michael Pratt +TryBot-Bypass: Michael Pratt +Reviewed-by: Carlos Amedee +--- + src/archive/tar/common.go | 1 + + src/archive/tar/reader.go | 9 +++++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go +index c667cfc..0454fcf 100644 +--- a/src/archive/tar/common.go ++++ b/src/archive/tar/common.go +@@ -34,6 +34,7 @@ var ( + errMissData = errors.New("archive/tar: sparse file references non-existent data") + errUnrefData = errors.New("archive/tar: sparse file contains unreferenced data") + errWriteHole = errors.New("archive/tar: write non-NUL byte in sparse hole") ++ errSparseTooLong = errors.New("archive/tar: sparse map too long") + ) + + type headerError []string +diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go +index f645af8..a4e5f27 100644 +--- a/src/archive/tar/reader.go ++++ b/src/archive/tar/reader.go +@@ -518,12 +518,17 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) { + cntNewline int64 + buf bytes.Buffer + blk block ++ totalSize int + ) + + // feedTokens copies data in blocks from r into buf until there are + // at least cnt newlines in buf. It will not read more blocks than needed. + feedTokens := func(n int64) error { + for cntNewline < n { ++ totalSize += len(blk) ++ if totalSize > maxSpecialFileSize { ++ return errSparseTooLong ++ } + if _, err := mustReadFull(r, blk[:]); err != nil { + return err + } +@@ -556,8 +561,8 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) { + } + + // Parse for all member entries. +- // numEntries is trusted after this since a potential attacker must have +- // committed resources proportional to what this library used. ++ // numEntries is trusted after this since feedTokens limits the number of ++ // tokens based on maxSpecialFileSize. + if err := feedTokens(2 * numEntries); err != nil { + return nil, err + } +-- +2.43.0 + diff --git a/0080-CVE-2025-58189-crypto-tls-quote-protocols-incrypto.patch b/0080-CVE-2025-58189-crypto-tls-quote-protocols-incrypto.patch new file mode 100644 index 0000000..1a0a5d2 --- /dev/null +++ b/0080-CVE-2025-58189-crypto-tls-quote-protocols-incrypto.patch @@ -0,0 +1,44 @@ +From 4e9006a716533fe1c7ee08df02dfc73078f7dc19 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Mon, 29 Sep 2025 10:11:56 -0700 +Subject: [PATCH] crypto/tls: quote protocols in ALPN + error message + +Quote the protocols sent by the client when returning the ALPN +negotiation error message. + +Reference: https://go-review.googlesource.com/c/go/+/707776 +Conclict: no + +Fixes CVE-2025-58189 +Fixes #75652 + +Change-Id: Ie7b3a1ed0b6efcc1705b71f0f1e8417126661330 +Reviewed-on: https://go-review.googlesource.com/c/go/+/707776 +Auto-Submit: Roland Shoemaker +Reviewed-by: Neal Patel +Reviewed-by: Nicholas Husin +Auto-Submit: Nicholas Husin +Reviewed-by: Nicholas Husin +TryBot-Bypass: Roland Shoemaker +Reviewed-by: Daniel McCarney +--- + src/crypto/tls/handshake_server.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go +index a5d8f4a..432f681 100644 +--- a/src/crypto/tls/handshake_server.go ++++ b/src/crypto/tls/handshake_server.go +@@ -302,7 +302,7 @@ func negotiateALPN(serverProtos, clientProtos []string) (string, error) { + if http11fallback { + return "", nil + } +- return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", clientProtos) ++ return "", fmt.Errorf("tls: client requested unsupported application protocols (%q)", clientProtos) + } + + // supportsECDHE returns whether ECDHE key exchanges can be used with this +-- +2.43.0 + diff --git a/0081-CVE-2025-61724-net-textproto-avoid-quadratic.patch b/0081-CVE-2025-61724-net-textproto-avoid-quadratic.patch new file mode 100644 index 0000000..92d6aed --- /dev/null +++ b/0081-CVE-2025-61724-net-textproto-avoid-quadratic.patch @@ -0,0 +1,70 @@ +From 5ede095649db7783726c28390812bca9ce2c684a Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Tue, 30 Sep 2025 15:11:16 -0700 +Subject: [PATCH] net/textproto: avoid quadratic complexity in + Reader.ReadResponse + +Reader.ReadResponse constructed a response string from repeated +string concatenation, permitting a malicious sender to cause excessive +memory allocation and CPU consumption by sending a response consisting +of many short lines. + +Reference: https://go-review.googlesource.com/c/go/+/709859 +Conclict: no + +Use a strings.Builder to construct the string instead. + +Thanks to Jakub Ciolek for reporting this issue. + +Fixes CVE-2025-61724 +Fixes #75716 + +Change-Id: I1a98ce85a21b830cb25799f9ac9333a67400d736 +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2940 +Reviewed-by: Roland Shoemaker +Reviewed-by: Nicholas Husin +Reviewed-on: https://go-review.googlesource.com/c/go/+/709859 +TryBot-Bypass: Michael Pratt +Auto-Submit: Michael Pratt +Reviewed-by: Carlos Amedee +--- + src/net/textproto/reader.go | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go +index 24d5e10..9fa166c 100644 +--- a/src/net/textproto/reader.go ++++ b/src/net/textproto/reader.go +@@ -288,8 +288,10 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err + // An expectCode <= 0 disables the check of the status code. + // + func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) { +- code, continued, message, err := r.readCodeLine(expectCode) ++ code, continued, first, err := r.readCodeLine(expectCode) + multi := continued ++ var messageBuilder strings.Builder ++ messageBuilder.WriteString(first) + for continued { + line, err := r.ReadLine() + if err != nil { +@@ -300,12 +302,15 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err + var moreMessage string + code2, continued, moreMessage, err = parseCodeLine(line, 0) + if err != nil || code2 != code { +- message += "\n" + strings.TrimRight(line, "\r\n") ++ messageBuilder.WriteByte('\n') ++ messageBuilder.WriteString(strings.TrimRight(line, "\r\n")) + continued = true + continue + } +- message += "\n" + moreMessage ++ messageBuilder.WriteByte('\n') ++ messageBuilder.WriteString(moreMessage) + } ++ message = messageBuilder.String() + if err != nil && multi && message != "" { + // replace one line error message with all lines (full message) + err = &Error{code, message} +-- +2.43.0 + diff --git a/0082-CVE-2025-58185-encoding-asn1-prevent-memory-exhaustion.patch b/0082-CVE-2025-58185-encoding-asn1-prevent-memory-exhaustion.patch new file mode 100644 index 0000000..7276b8e --- /dev/null +++ b/0082-CVE-2025-58185-encoding-asn1-prevent-memory-exhaustion.patch @@ -0,0 +1,166 @@ +From 8709a41d5ef7321f486a1857f189c3fee20e8edd Mon Sep 17 00:00:00 2001 +From: Nicholas Husin +Date: Wed, 03 Sep 2025 09:30:56 -0400 +Subject: [PATCH] encoding/asn1: prevent memory exhaustion when + parsing using internal/saferio + +Within parseSequenceOf, reflect.MakeSlice is being used to pre-allocate +a slice that is needed in order to fully validate the given DER payload. +The size of the slice allocated are also multiple times larger than the +input DER: + +Reference: https://go-review.googlesource.com/c/go/+/709856 +Conflict: no + +- When using asn1.Unmarshal directly, the allocated slice is ~28x + larger. +- When passing in DER using x509.ParseCertificateRequest, the allocated + slice is ~48x larger. +- When passing in DER using ocsp.ParseResponse, the allocated slice is + ~137x larger. + +As a result, a malicious actor can craft a big empty DER payload, +resulting in an unnecessary large allocation of memories. This can be a +way to cause memory exhaustion. + +To prevent this, we now use SliceCapWithSize within internal/saferio to +enforce a memory allocation cap. + +Thanks to Jakub Ciolek for reporting this issue. + +For #75671 +Fixes CVE-2025-58185 + +Change-Id: Id50e76187eda43f594be75e516b9ca1d2ae6f428 +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2700 +Reviewed-by: Roland Shoemaker +Reviewed-by: Damien Neil +Reviewed-on: https://go-review.googlesource.com/c/go/+/709856 +Reviewed-by: Carlos Amedee +LUCI-TryBot-Result: Go LUCI +Auto-Submit: Michael Pratt +--- + src/encoding/asn1/asn1.go | 32 ++++++++++++++++++++++++++-- + src/encoding/asn1/asn1_test.go | 38 ++++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+), 2 deletions(-) + +diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go +index cffc06d..0a159ef 100644 +--- a/src/encoding/asn1/asn1.go ++++ b/src/encoding/asn1/asn1.go +@@ -30,7 +30,7 @@ import ( + "unicode/utf16" + "unicode/utf8" + ) +- ++const chunk = 10 << 20 // 10M + // A StructuralError suggests that the ASN.1 data is valid, but the Go type + // which is receiving it doesn't match. + type StructuralError struct { +@@ -71,6 +71,28 @@ func parseBool(bytes []byte) (ret bool, err error) { + return + } + ++// SliceCap is a local copy of internal/saferio.SliceCap ++func sliceCap(v interface{},c uint64) int { ++ if int64(c) < 0 || c != uint64(int(c)) { ++ return -1 ++ } ++ typ := reflect.TypeOf(v) ++ if typ.Kind() !=reflect.Ptr { ++ panic("SliceCap called with non-pointer type") ++ } ++ size := uint64(typ.Elem().Size()) ++ if size > 0 && c > (1<<64-1)/size { ++ return -1 ++ } ++ if c*size > chunk { ++ c = uint64(chunk / size) ++ if c == 0{ ++ c = 1 ++ } ++ } ++ return int(c) ++} ++ + // INTEGER + + // checkInteger returns nil if the given bytes are a valid DER-encoded +@@ -640,10 +662,16 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type + offset += t.length + numElements++ + } +- ret = reflect.MakeSlice(sliceType, numElements, numElements) ++ safeCap := sliceCap(reflect.Zero(reflect.PtrTo(elemType)).Interface(), uint64(numElements)) ++ if safeCap < 0 { ++ err = SyntaxError{fmt.Sprintf("%s slice too big: %d elements of %d bytes", elemType.Kind(), numElements, elemType.Size())} ++ return ++ } ++ ret = reflect.MakeSlice(sliceType, 0, safeCap) + params := fieldParameters{} + offset := 0 + for i := 0; i < numElements; i++ { ++ ret = reflect.Append(ret, reflect.Zero(elemType)) + offset, err = parseField(ret.Index(i), bytes, offset, params) + if err != nil { + return +diff --git a/src/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go +index 8985538..553e391 100644 +--- a/src/encoding/asn1/asn1_test.go ++++ b/src/encoding/asn1/asn1_test.go +@@ -7,10 +7,12 @@ package asn1 + import ( + "bytes" + "encoding/hex" ++ "errors" + "fmt" + "math" + "math/big" + "reflect" ++ "runtime" + "strings" + "testing" + "time" +@@ -1164,3 +1166,39 @@ func TestNonMinimalEncodedOID(t *testing.T) { + t.Fatalf("accepted non-minimally encoded oid") + } + } ++ ++func TestParsingMemoryConsumption(t *testing.T) { ++ // Craft a syntatically valid, but empty, ~10 MB DER bomb. A successful ++ // unmarshal of this bomb should yield ~280 MB. However, the parsing should ++ // fail due to the empty content; and, in such cases, we want to make sure ++ // that we do not unnecessarily allocate memories. ++ derBomb := make([]byte, 10_000_000) ++ for i := range derBomb { ++ derBomb[i] = 0x30 ++ } ++ derBomb = append([]byte{0x30, 0x83, 0x98, 0x96, 0x80}, derBomb...) ++ ++ var m runtime.MemStats ++ runtime.GC() ++ runtime.ReadMemStats(&m) ++ memBefore := m.TotalAlloc ++ ++ var out []struct { ++ Id []int ++ Critical bool `asn1:"optional"` ++ Value []byte ++ } ++ _, err := Unmarshal(derBomb, &out) ++ if !errors.As(err, &SyntaxError{}) { ++ t.Fatalf("Incorrect error result: want (%v), but got (%v) instead", &SyntaxError{}, err) ++ } ++ ++ runtime.ReadMemStats(&m) ++ memDiff := m.TotalAlloc - memBefore ++ ++ // Ensure that the memory allocated does not exceed 10<<21 (~20 MB) when ++ // the parsing fails. ++ if memDiff > 10<<21 { ++ t.Errorf("Too much memory allocated while parsing DER: %v MiB", memDiff/1024/1024) ++ } ++} +-- +2.43.0 + diff --git a/golang.spec b/golang.spec index 9d5f029..86ba593 100644 --- a/golang.spec +++ b/golang.spec @@ -63,7 +63,7 @@ Name: golang Version: 1.17.3 -Release: 42 +Release: 43 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -228,6 +228,10 @@ Patch6075: 0075-CVE-2025-4673-net-http-strip-sensitive-proxy-headers.patch Patch6076: 0076-CVE-2025-47907-database-sql-avoid-closing-Rows-while-scan-is-in-pro.patch Patch6077: 0077-CVE-2025-47906-os-exec-fix-incorrect-expansion-of-.-and-.-in-LookPa.patch Patch6078: 0078-backport-CVE-2025-22871-net-http-reject-newlines-in-.patch +Patch6079: 0079-CVE-2025-58183-archive-tar-set-a-limit-on-the.patch +Patch6080: 0080-CVE-2025-58189-crypto-tls-quote-protocols-incrypto.patch +Patch6081: 0081-CVE-2025-61724-net-textproto-avoid-quadratic.patch +Patch6082: 0082-CVE-2025-58185-encoding-asn1-prevent-memory-exhaustion.patch ExclusiveArch: %{golang_arches} @@ -466,6 +470,12 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Sat Nov 8 2025 huzhangying - 1.17.3-43 +- Type:CVE +- CVE:CVE-2025-58183,CVE-2025-58185,CVE-2025-58189,CVE-2025-61724 +- SUG:NA +- DESC:fix CVE-2025-58183,CVE-2025-58185,CVE-2025-58189,CVE-2025-61724 + * Wed Aug 27 2025 songliyang - 1.17.3-42 - Type:CVE - CVE:CVE-2025-22871 -- Gitee