[Backport-20.03-LTS-SP4]fix CVE-2024-34156

This commit is contained in:
wangshuo 2024-11-04 15:10:22 +08:00
parent 335a89266d
commit 535cf6f207
2 changed files with 152 additions and 2 deletions

View File

@ -0,0 +1,143 @@
From 08c84420bc40d1cd5eb71b85cbe3a36f707bdb3f Mon Sep 17 00:00:00 2001
From: Roland Shoemaker <bracewell@google.com>
Date: Fri, 03 May 2024 09:21:39 -0400
Subject: [PATCH] encoding/gob: cover missed cases when checking ignore depth
This change makes sure that we are properly checking the ignored field
recursion depth in decIgnoreOpFor consistently. This prevents stack
exhaustion when attempting to decode a message that contains an
extremely deeply nested struct which is ignored.
Thanks to Md Sakib Anwar of The Ohio State University (anwar.40@osu.edu)
for reporting this issue.
Fixes #69139
Fixes CVE-2024-34156
Edited-by: Wang Shuo <wangshuo@kylinos.cn>
Change-Id: Iacce06be95a5892b3064f1c40fcba2e2567862d6
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1440
Reviewed-by: Russ Cox <rsc@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/611239
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
---
src/encoding/gob/decode.go | 19 +++++++++++--------
src/encoding/gob/decoder.go | 2 ++
src/encoding/gob/gobencdec_test.go | 14 ++++++++++++++
3 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go
index 0e0ec75..92d64cb 100644
--- a/src/encoding/gob/decode.go
+++ b/src/encoding/gob/decode.go
@@ -874,8 +874,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
var maxIgnoreNestingDepth = 10000
// decIgnoreOpFor returns the decoding op for a field that has no destination.
-func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp {
- if depth > maxIgnoreNestingDepth {
+func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp {
+ // Track how deep we've recursed trying to skip nested ignored fields.
+ dec.ignoreDepth++
+ defer func() { dec.ignoreDepth-- }()
+ if dec.ignoreDepth > maxIgnoreNestingDepth {
error_(errors.New("invalid nesting depth"))
}
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
@@ -901,7 +904,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp,
errorf("bad data: undefined type %s", wireId.string())
case wire.ArrayT != nil:
elemId := wire.ArrayT.Elem
- elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
+ elemOp := dec.decIgnoreOpFor(elemId, inProgress)
op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len)
}
@@ -909,15 +912,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp,
case wire.MapT != nil:
keyId := dec.wireType[wireId].MapT.Key
elemId := dec.wireType[wireId].MapT.Elem
- keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1)
- elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
+ keyOp := dec.decIgnoreOpFor(keyId, inProgress)
+ elemOp := dec.decIgnoreOpFor(elemId, inProgress)
op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreMap(state, *keyOp, *elemOp)
}
case wire.SliceT != nil:
elemId := wire.SliceT.Elem
- elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
+ elemOp := dec.decIgnoreOpFor(elemId, inProgress)
op = func(i *decInstr, state *decoderState, value reflect.Value) {
state.dec.ignoreSlice(state, *elemOp)
}
@@ -1078,7 +1081,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de
func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine {
engine := new(decEngine)
engine.instr = make([]decInstr, 1) // one item
- op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0)
+ op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp))
ovfl := overflow(dec.typeString(remoteId))
engine.instr[0] = decInstr{*op, 0, nil, ovfl}
engine.numInstr = 1
@@ -1123,7 +1126,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
localField, present := srt.FieldByName(wireField.Name)
// TODO(r): anonymous names
if !present || !isExported(wireField.Name) {
- op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0)
+ op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp))
engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl}
continue
}
diff --git a/src/encoding/gob/decoder.go b/src/encoding/gob/decoder.go
index b52aabe..0d37b9d 100644
--- a/src/encoding/gob/decoder.go
+++ b/src/encoding/gob/decoder.go
@@ -34,6 +34,8 @@ type Decoder struct {
freeList *decoderState // list of free decoderStates; avoids reallocation
countBuf []byte // used for decoding integers while parsing messages
err error
+ // ignoreDepth tracks the depth of recursively parsed ignored fields
+ ignoreDepth int
}
// NewDecoder returns a new decoder that reads from the io.Reader.
diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go
index 1b52ecc..2b5f2a8 100644
--- a/src/encoding/gob/gobencdec_test.go
+++ b/src/encoding/gob/gobencdec_test.go
@@ -806,6 +806,8 @@ func TestIngoreDepthLimit(t *testing.T) {
defer func() { maxIgnoreNestingDepth = oldNestingDepth }()
b := new(bytes.Buffer)
enc := NewEncoder(b)
+
+ // Nested slice
typ := reflect.TypeOf(int(0))
nested := reflect.ArrayOf(1, typ)
for i := 0; i < 100; i++ {
@@ -819,4 +821,16 @@ func TestIngoreDepthLimit(t *testing.T) {
if err := dec.Decode(&output); err == nil || err.Error() != expectedErr {
t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err)
}
+
+ // Nested struct
+ nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: typ}})
+ for i := 0; i < 100; i++ {
+ nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})
+ }
+ badStruct = reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}))
+ enc.Encode(badStruct.Interface())
+ dec = NewDecoder(b)
+ if err := dec.Decode(&output); err == nil || err.Error() != expectedErr {
+ t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err)
+ }
}
--
2.27.0

View File

@ -58,7 +58,7 @@
Name: golang
Version: 1.15.7
Release: 47
Release: 48
Summary: The Go Programming Language
License: BSD and Public Domain
URL: https://golang.org/
@ -265,7 +265,8 @@ Patch6120: 0120-Backport-net-http-update-bundled-golang.org-x-net-ht.patch
Patch6121: 0121-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch
Patch6122: 0122-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch
Patch6123: 0123-Backport-net-http-send-body-or-close-connection-on-e.patch
Patch6124: 0124-CVE-2024-34155-track-depth-in-nested-element-lists.patch
Patch6124: 0124-CVE-2024-34155-track-depth-in-nested-element-lists.patch
Patch6125: 0125-Backport-encoding-gob-cover-missed-cases-when-checking-ignore.patch
Patch9001: 0001-drop-hard-code-cert.patch
@ -506,6 +507,12 @@ fi
%files devel -f go-tests.list -f go-misc.list -f go-src.list
%changelog
* Mon Nov 04 2024 wangshuo <wangshuo@kylinops.cn> - 1.15.7-48
- Type:CVE
- CVE:CVE-2024-34156
- SUG:NA
- DESC:fix CVE-2024-34156
* Fri Sep 13 2024 Yu Peng <yupeng@kylinos.cn> - 1.15.7-47
- Type:CVE
- CVE:CVE-2024-34155