diff --git a/meta/recipes-devtools/go/go-1.22.12.inc b/meta/recipes-devtools/go/go-1.22.12.inc index a364e1aae8..38992219c8 100644 --- a/meta/recipes-devtools/go/go-1.22.12.inc +++ b/meta/recipes-devtools/go/go-1.22.12.inc @@ -21,6 +21,7 @@ SRC_URI += "\ file://CVE-2025-47907-pre.patch \ file://CVE-2025-47907.patch \ file://CVE-2025-47906.patch \ + file://CVE-2025-58185.patch \ " SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71" diff --git a/meta/recipes-devtools/go/go/CVE-2025-58185.patch b/meta/recipes-devtools/go/go/CVE-2025-58185.patch new file mode 100644 index 0000000000..63250614ce --- /dev/null +++ b/meta/recipes-devtools/go/go/CVE-2025-58185.patch @@ -0,0 +1,142 @@ +From 5c3d61c886f7ecfce9a6d6d3c97e6d5a8afb17d1 Mon Sep 17 00:00:00 2001 +From: Nicholas Husin +Date: Wed, 3 Sep 2025 09:30:56 -0400 +Subject: [PATCH] [release-branch.go1.24] 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: + +- 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 #75704 +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-internal-review.googlesource.com/c/go/+/2984 +Reviewed-by: Nicholas Husin +Reviewed-on: https://go-review.googlesource.com/c/go/+/709841 +Reviewed-by: Carlos Amedee +Auto-Submit: Michael Pratt +TryBot-Bypass: Michael Pratt + +CVE: CVE-2025-58185 + +Upstream-Status: Backport [https://github.com/golang/go/commit/5c3d61c886f7ecfce9a6d6d3c97e6d5a8afb17d1] + +Signed-off-by: Archana Polampalli +--- + src/encoding/asn1/asn1.go | 10 ++++++++- + src/encoding/asn1/asn1_test.go | 38 ++++++++++++++++++++++++++++++++++ + 2 files changed, 47 insertions(+), 1 deletion(-) + +diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go +index 781ab87..16c7138 100644 +--- a/src/encoding/asn1/asn1.go ++++ b/src/encoding/asn1/asn1.go +@@ -22,6 +22,7 @@ package asn1 + import ( + "errors" + "fmt" ++ "internal/saferio" + "math" + "math/big" + "reflect" +@@ -643,10 +644,17 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type + offset += t.length + numElements++ + } +- ret = reflect.MakeSlice(sliceType, numElements, numElements) ++ elemSize := uint64(elemType.Size()) ++ safeCap := saferio.SliceCapWithSize(elemSize, uint64(numElements)) ++ if safeCap < 0 { ++ err = SyntaxError{fmt.Sprintf("%s slice too big: %d elements of %d bytes", elemType.Kind(), numElements, elemSize)} ++ 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 9a605e2..249d4e4 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" +@@ -1175,3 +1177,39 @@ func BenchmarkObjectIdentifierString(b *testing.B) { + _ = oidPublicKeyRSA.String() + } + } ++ ++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.40.0