diff mbox series

[scarthgap,1/7] go: fix CVE-2025-58185

Message ID 20251107102103.436637-1-archana.polampalli@windriver.com
State Under Review
Delegated to: Steve Sakoman
Headers show
Series [scarthgap,1/7] go: fix CVE-2025-58185 | expand

Commit Message

Polampalli, Archana Nov. 7, 2025, 10:20 a.m. UTC
From: Archana Polampalli <archana.polampalli@windriver.com>

Parsing a maliciously crafted DER payload could allocate large amounts of memory,
causing memory exhaustion.

Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
---
 meta/recipes-devtools/go/go-1.22.12.inc       |   1 +
 .../go/go/CVE-2025-58185.patch                | 142 ++++++++++++++++++
 2 files changed, 143 insertions(+)
 create mode 100644 meta/recipes-devtools/go/go/CVE-2025-58185.patch
diff mbox series

Patch

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 <husin@google.com>
+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 <bracewell@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2984
+Reviewed-by: Nicholas Husin <husin@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/709841
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+Auto-Submit: Michael Pratt <mpratt@google.com>
+TryBot-Bypass: Michael Pratt <mpratt@google.com>
+
+CVE: CVE-2025-58185
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/5c3d61c886f7ecfce9a6d6d3c97e6d5a8afb17d1]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ 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