diff options
author | Archana Polampalli <archana.polampalli@windriver.com> | 2025-01-08 05:54:20 +0000 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2025-01-18 06:21:02 -0800 |
commit | 0c88d20540f0513c3d79d10f34132b2296ac246c (patch) | |
tree | 246daee0e389be0f6fbe8910c19a1d5496f5eedb | |
parent | f700dcdc1d7db04c126a42f1d8f9588ad295f09c (diff) | |
download | poky-0c88d20540f0513c3d79d10f34132b2296ac246c.tar.gz |
go: Fix CVE-2024-34156
Calling Decoder.Decode on a message which contains deeply nested structures can
cause a panic due to stack exhaustion. This is a follow-up to CVE-2022-30635.
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2024-34156
Upstream-patch:
https://github.com/golang/go/commit/2092294f2b097c5828f4eace6c98a322c1510b01
(From OE-Core rev: 3aeeee86a53cee14bb1a6a485f8781459b6f2ffc)
Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r-- | meta/recipes-devtools/go/go-1.17.13.inc | 1 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.21/CVE-2024-34156.patch | 150 |
2 files changed, 151 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc index 11bd2afde0..53ca869221 100644 --- a/meta/recipes-devtools/go/go-1.17.13.inc +++ b/meta/recipes-devtools/go/go-1.17.13.inc | |||
@@ -59,6 +59,7 @@ SRC_URI += "\ | |||
59 | file://CVE-2024-24789.patch \ | 59 | file://CVE-2024-24789.patch \ |
60 | file://CVE-2024-24791.patch \ | 60 | file://CVE-2024-24791.patch \ |
61 | file://CVE-2024-34155.patch \ | 61 | file://CVE-2024-34155.patch \ |
62 | file://CVE-2024-34156.patch \ | ||
62 | " | 63 | " |
63 | SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd" | 64 | SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd" |
64 | 65 | ||
diff --git a/meta/recipes-devtools/go/go-1.21/CVE-2024-34156.patch b/meta/recipes-devtools/go/go-1.21/CVE-2024-34156.patch new file mode 100644 index 0000000000..d8a915d6e9 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.21/CVE-2024-34156.patch | |||
@@ -0,0 +1,150 @@ | |||
1 | From 2092294f2b097c5828f4eace6c98a322c1510b01 Mon Sep 17 00:00:00 2001 | ||
2 | From: Roland Shoemaker <bracewell@google.com> | ||
3 | Date: Fri, 3 May 2024 09:21:39 -0400 | ||
4 | Subject: [PATCH] encoding/gob: cover missed cases when checking ignore depth | ||
5 | |||
6 | This change makes sure that we are properly checking the ignored field | ||
7 | recursion depth in decIgnoreOpFor consistently. This prevents stack | ||
8 | exhaustion when attempting to decode a message that contains an | ||
9 | extremely deeply nested struct which is ignored. | ||
10 | |||
11 | Thanks to Md Sakib Anwar of The Ohio State University (anwar.40@osu.edu) | ||
12 | for reporting this issue. | ||
13 | |||
14 | Updates #69139 | ||
15 | Fixes #69144 | ||
16 | Fixes CVE-2024-34156 | ||
17 | |||
18 | Change-Id: Iacce06be95a5892b3064f1c40fcba2e2567862d6 | ||
19 | Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1440 | ||
20 | Reviewed-by: Russ Cox <rsc@google.com> | ||
21 | Reviewed-by: Damien Neil <dneil@google.com> | ||
22 | (cherry picked from commit f0a11f9b3aaa362cb1d05e095e3c8d421d4f087f) | ||
23 | Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1580 | ||
24 | Reviewed-by: Tatiana Bradley <tatianabradley@google.com> | ||
25 | Reviewed-on: https://go-review.googlesource.com/c/go/+/611182 | ||
26 | TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com> | ||
27 | Reviewed-by: Michael Pratt <mpratt@google.com> | ||
28 | Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> | ||
29 | Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> | ||
30 | |||
31 | CVE: CVE-2024-34156 | ||
32 | |||
33 | Upstream-Status: Backport [https://github.com/golang/go/commit/2092294f2b097c5828f4eace6c98a322c1510b01] | ||
34 | |||
35 | Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> | ||
36 | --- | ||
37 | src/encoding/gob/decode.go | 19 +++++++++++-------- | ||
38 | src/encoding/gob/decoder.go | 2 ++ | ||
39 | src/encoding/gob/gobencdec_test.go | 14 ++++++++++++++ | ||
40 | 3 files changed, 27 insertions(+), 8 deletions(-) | ||
41 | |||
42 | diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go | ||
43 | index 0e0ec75..92d64cb 100644 | ||
44 | --- a/src/encoding/gob/decode.go | ||
45 | +++ b/src/encoding/gob/decode.go | ||
46 | @@ -874,8 +874,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg | ||
47 | var maxIgnoreNestingDepth = 10000 | ||
48 | |||
49 | // decIgnoreOpFor returns the decoding op for a field that has no destination. | ||
50 | -func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp { | ||
51 | - if depth > maxIgnoreNestingDepth { | ||
52 | +func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp { | ||
53 | + // Track how deep we've recursed trying to skip nested ignored fields. | ||
54 | + dec.ignoreDepth++ | ||
55 | + defer func() { dec.ignoreDepth-- }() | ||
56 | + if dec.ignoreDepth > maxIgnoreNestingDepth { | ||
57 | error_(errors.New("invalid nesting depth")) | ||
58 | } | ||
59 | // If this type is already in progress, it's a recursive type (e.g. map[string]*T). | ||
60 | @@ -901,7 +904,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, | ||
61 | errorf("bad data: undefined type %s", wireId.string()) | ||
62 | case wire.ArrayT != nil: | ||
63 | elemId := wire.ArrayT.Elem | ||
64 | - elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) | ||
65 | + elemOp := dec.decIgnoreOpFor(elemId, inProgress) | ||
66 | op = func(i *decInstr, state *decoderState, value reflect.Value) { | ||
67 | state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len) | ||
68 | } | ||
69 | @@ -909,15 +912,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, | ||
70 | case wire.MapT != nil: | ||
71 | keyId := dec.wireType[wireId].MapT.Key | ||
72 | elemId := dec.wireType[wireId].MapT.Elem | ||
73 | - keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1) | ||
74 | - elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) | ||
75 | + keyOp := dec.decIgnoreOpFor(keyId, inProgress) | ||
76 | + elemOp := dec.decIgnoreOpFor(elemId, inProgress) | ||
77 | op = func(i *decInstr, state *decoderState, value reflect.Value) { | ||
78 | state.dec.ignoreMap(state, *keyOp, *elemOp) | ||
79 | } | ||
80 | |||
81 | case wire.SliceT != nil: | ||
82 | elemId := wire.SliceT.Elem | ||
83 | - elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) | ||
84 | + elemOp := dec.decIgnoreOpFor(elemId, inProgress) | ||
85 | op = func(i *decInstr, state *decoderState, value reflect.Value) { | ||
86 | state.dec.ignoreSlice(state, *elemOp) | ||
87 | } | ||
88 | @@ -1078,7 +1081,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de | ||
89 | func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine { | ||
90 | engine := new(decEngine) | ||
91 | engine.instr = make([]decInstr, 1) // one item | ||
92 | - op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0) | ||
93 | + op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp)) | ||
94 | ovfl := overflow(dec.typeString(remoteId)) | ||
95 | engine.instr[0] = decInstr{*op, 0, nil, ovfl} | ||
96 | engine.numInstr = 1 | ||
97 | @@ -1123,7 +1126,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn | ||
98 | localField, present := srt.FieldByName(wireField.Name) | ||
99 | // TODO(r): anonymous names | ||
100 | if !present || !isExported(wireField.Name) { | ||
101 | - op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0) | ||
102 | + op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp)) | ||
103 | engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl} | ||
104 | continue | ||
105 | } | ||
106 | diff --git a/src/encoding/gob/decoder.go b/src/encoding/gob/decoder.go | ||
107 | index b476aaa..8fab2fd 100644 | ||
108 | --- a/src/encoding/gob/decoder.go | ||
109 | +++ b/src/encoding/gob/decoder.go | ||
110 | @@ -34,6 +34,8 @@ type Decoder struct { | ||
111 | freeList *decoderState // list of free decoderStates; avoids reallocation | ||
112 | countBuf []byte // used for decoding integers while parsing messages | ||
113 | err error | ||
114 | + // ignoreDepth tracks the depth of recursively parsed ignored fields | ||
115 | + ignoreDepth int | ||
116 | } | ||
117 | |||
118 | // NewDecoder returns a new decoder that reads from the io.Reader. | ||
119 | diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go | ||
120 | index 1b52ecc..2b5f2a8 100644 | ||
121 | --- a/src/encoding/gob/gobencdec_test.go | ||
122 | +++ b/src/encoding/gob/gobencdec_test.go | ||
123 | @@ -806,6 +806,8 @@ func TestIngoreDepthLimit(t *testing.T) { | ||
124 | defer func() { maxIgnoreNestingDepth = oldNestingDepth }() | ||
125 | b := new(bytes.Buffer) | ||
126 | enc := NewEncoder(b) | ||
127 | + | ||
128 | + // Nested slice | ||
129 | typ := reflect.TypeOf(int(0)) | ||
130 | nested := reflect.ArrayOf(1, typ) | ||
131 | for i := 0; i < 100; i++ { | ||
132 | @@ -819,4 +821,16 @@ func TestIngoreDepthLimit(t *testing.T) { | ||
133 | if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { | ||
134 | t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) | ||
135 | } | ||
136 | + | ||
137 | + // Nested struct | ||
138 | + nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: typ}}) | ||
139 | + for i := 0; i < 100; i++ { | ||
140 | + nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}) | ||
141 | + } | ||
142 | + badStruct = reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})) | ||
143 | + enc.Encode(badStruct.Interface()) | ||
144 | + dec = NewDecoder(b) | ||
145 | + if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { | ||
146 | + t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) | ||
147 | + } | ||
148 | } | ||
149 | -- | ||
150 | 2.40.0 | ||