mirror of
https://git.yoctoproject.org/poky
synced 2026-05-07 04:58:26 +00:00
go: fix CVE-2025-58185
Parsing a maliciously crafted DER payload could allocate large amounts of memory, causing memory exhaustion. (From OE-Core rev: f27acc863ee34b56e2c49dc96ad2b58fb35e2d46) Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
This commit is contained in:
committed by
Steve Sakoman
parent
604b1627ed
commit
0c4e028627
@@ -21,6 +21,7 @@ SRC_URI += "\
|
|||||||
file://CVE-2025-47907-pre.patch \
|
file://CVE-2025-47907-pre.patch \
|
||||||
file://CVE-2025-47907.patch \
|
file://CVE-2025-47907.patch \
|
||||||
file://CVE-2025-47906.patch \
|
file://CVE-2025-47906.patch \
|
||||||
|
file://CVE-2025-58185.patch \
|
||||||
"
|
"
|
||||||
SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
|
SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
Reference in New Issue
Block a user