diff options
author | Hitendra Prajapati <hprajapati@mvista.com> | 2022-06-24 17:00:02 +0530 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-07-08 08:27:20 +0100 |
commit | 3f2da49c2b6c16bcca84496e7fc6102952786605 (patch) | |
tree | 1133286a0ffbe944ce1924144c227f9cfdb6f246 /meta/recipes-devtools/go | |
parent | 02867c90395db2ebfbcaed3d0d813b889978888c (diff) | |
download | poky-3f2da49c2b6c16bcca84496e7fc6102952786605.tar.gz |
golang: CVE-2022-24675 encoding/pem: fix stack overflow in Decode
Source: https://go-review.googlesource.com/c/go
MR: 117551
Type: Security Fix
Disposition: Backport from https://go-review.googlesource.com/c/go/+/399816/
ChangeID: 347f22f93e8eaecb3d39f8d6c0fe5a70c5cf7b7c
Description:
CVE-2022-24675 golang: encoding/pem: fix stack overflow in Decode.
(From OE-Core rev: 6625e24a6143765ce2e4e08d25e3fe021bc2cdf6)
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/go')
-rw-r--r-- | meta/recipes-devtools/go/go-1.14.inc | 1 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch | 271 |
2 files changed, 272 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14.inc b/meta/recipes-devtools/go/go-1.14.inc index 4827c6adfa..773d252bd1 100644 --- a/meta/recipes-devtools/go/go-1.14.inc +++ b/meta/recipes-devtools/go/go-1.14.inc | |||
@@ -23,6 +23,7 @@ SRC_URI += "\ | |||
23 | file://CVE-2022-23806.patch \ | 23 | file://CVE-2022-23806.patch \ |
24 | file://CVE-2022-23772.patch \ | 24 | file://CVE-2022-23772.patch \ |
25 | file://CVE-2021-44717.patch \ | 25 | file://CVE-2021-44717.patch \ |
26 | file://CVE-2022-24675.patch \ | ||
26 | " | 27 | " |
27 | 28 | ||
28 | SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch" | 29 | SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch" |
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch new file mode 100644 index 0000000000..4bc012be21 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch | |||
@@ -0,0 +1,271 @@ | |||
1 | From 1eb931d60a24501a9668e5cb4647593e19115507 Mon Sep 17 00:00:00 2001 | ||
2 | From: Hitendra Prajapati <hprajapati@mvista.com> | ||
3 | Date: Fri, 17 Jun 2022 12:22:53 +0530 | ||
4 | Subject: [PATCH] CVE-2022-24675 | ||
5 | |||
6 | Upstream-Status: Backport [https://go-review.googlesource.com/c/go/+/399816/] | ||
7 | CVE: CVE-2022-24675 | ||
8 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> | ||
9 | --- | ||
10 | src/encoding/pem/pem.go | 174 +++++++++++++++-------------------- | ||
11 | src/encoding/pem/pem_test.go | 28 +++++- | ||
12 | 2 files changed, 101 insertions(+), 101 deletions(-) | ||
13 | |||
14 | diff --git a/src/encoding/pem/pem.go b/src/encoding/pem/pem.go | ||
15 | index a7272da..1bee1c1 100644 | ||
16 | --- a/src/encoding/pem/pem.go | ||
17 | +++ b/src/encoding/pem/pem.go | ||
18 | @@ -87,123 +87,97 @@ func Decode(data []byte) (p *Block, rest []byte) { | ||
19 | // pemStart begins with a newline. However, at the very beginning of | ||
20 | // the byte array, we'll accept the start string without it. | ||
21 | rest = data | ||
22 | - if bytes.HasPrefix(data, pemStart[1:]) { | ||
23 | - rest = rest[len(pemStart)-1 : len(data)] | ||
24 | - } else if i := bytes.Index(data, pemStart); i >= 0 { | ||
25 | - rest = rest[i+len(pemStart) : len(data)] | ||
26 | - } else { | ||
27 | - return nil, data | ||
28 | - } | ||
29 | - | ||
30 | - typeLine, rest := getLine(rest) | ||
31 | - if !bytes.HasSuffix(typeLine, pemEndOfLine) { | ||
32 | - return decodeError(data, rest) | ||
33 | - } | ||
34 | - typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)] | ||
35 | - | ||
36 | - p = &Block{ | ||
37 | - Headers: make(map[string]string), | ||
38 | - Type: string(typeLine), | ||
39 | - } | ||
40 | - | ||
41 | for { | ||
42 | - // This loop terminates because getLine's second result is | ||
43 | - // always smaller than its argument. | ||
44 | - if len(rest) == 0 { | ||
45 | + if bytes.HasPrefix(rest, pemStart[1:]) { | ||
46 | + rest = rest[len(pemStart)-1:] | ||
47 | + } else if i := bytes.Index(rest, pemStart); i >= 0 { | ||
48 | + rest = rest[i+len(pemStart) : len(rest)] | ||
49 | + } else { | ||
50 | return nil, data | ||
51 | } | ||
52 | - line, next := getLine(rest) | ||
53 | |||
54 | - i := bytes.IndexByte(line, ':') | ||
55 | - if i == -1 { | ||
56 | - break | ||
57 | + var typeLine []byte | ||
58 | + typeLine, rest = getLine(rest) | ||
59 | + if !bytes.HasSuffix(typeLine, pemEndOfLine) { | ||
60 | + continue | ||
61 | } | ||
62 | + typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)] | ||
63 | |||
64 | - // TODO(agl): need to cope with values that spread across lines. | ||
65 | - key, val := line[:i], line[i+1:] | ||
66 | - key = bytes.TrimSpace(key) | ||
67 | - val = bytes.TrimSpace(val) | ||
68 | - p.Headers[string(key)] = string(val) | ||
69 | - rest = next | ||
70 | - } | ||
71 | + p = &Block{ | ||
72 | + Headers: make(map[string]string), | ||
73 | + Type: string(typeLine), | ||
74 | + } | ||
75 | |||
76 | - var endIndex, endTrailerIndex int | ||
77 | + for { | ||
78 | + // This loop terminates because getLine's second result is | ||
79 | + // always smaller than its argument. | ||
80 | + if len(rest) == 0 { | ||
81 | + return nil, data | ||
82 | + } | ||
83 | + line, next := getLine(rest) | ||
84 | |||
85 | - // If there were no headers, the END line might occur | ||
86 | - // immediately, without a leading newline. | ||
87 | - if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) { | ||
88 | - endIndex = 0 | ||
89 | - endTrailerIndex = len(pemEnd) - 1 | ||
90 | - } else { | ||
91 | - endIndex = bytes.Index(rest, pemEnd) | ||
92 | - endTrailerIndex = endIndex + len(pemEnd) | ||
93 | - } | ||
94 | + i := bytes.IndexByte(line, ':') | ||
95 | + if i == -1 { | ||
96 | + break | ||
97 | + } | ||
98 | |||
99 | - if endIndex < 0 { | ||
100 | - return decodeError(data, rest) | ||
101 | - } | ||
102 | + // TODO(agl): need to cope with values that spread across lines. | ||
103 | + key, val := line[:i], line[i+1:] | ||
104 | + key = bytes.TrimSpace(key) | ||
105 | + val = bytes.TrimSpace(val) | ||
106 | + p.Headers[string(key)] = string(val) | ||
107 | + rest = next | ||
108 | + } | ||
109 | |||
110 | - // After the "-----" of the ending line, there should be the same type | ||
111 | - // and then a final five dashes. | ||
112 | - endTrailer := rest[endTrailerIndex:] | ||
113 | - endTrailerLen := len(typeLine) + len(pemEndOfLine) | ||
114 | - if len(endTrailer) < endTrailerLen { | ||
115 | - return decodeError(data, rest) | ||
116 | - } | ||
117 | + var endIndex, endTrailerIndex int | ||
118 | |||
119 | - restOfEndLine := endTrailer[endTrailerLen:] | ||
120 | - endTrailer = endTrailer[:endTrailerLen] | ||
121 | - if !bytes.HasPrefix(endTrailer, typeLine) || | ||
122 | - !bytes.HasSuffix(endTrailer, pemEndOfLine) { | ||
123 | - return decodeError(data, rest) | ||
124 | - } | ||
125 | + // If there were no headers, the END line might occur | ||
126 | + // immediately, without a leading newline. | ||
127 | + if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) { | ||
128 | + endIndex = 0 | ||
129 | + endTrailerIndex = len(pemEnd) - 1 | ||
130 | + } else { | ||
131 | + endIndex = bytes.Index(rest, pemEnd) | ||
132 | + endTrailerIndex = endIndex + len(pemEnd) | ||
133 | + } | ||
134 | |||
135 | - // The line must end with only whitespace. | ||
136 | - if s, _ := getLine(restOfEndLine); len(s) != 0 { | ||
137 | - return decodeError(data, rest) | ||
138 | - } | ||
139 | + if endIndex < 0 { | ||
140 | + continue | ||
141 | + } | ||
142 | |||
143 | - base64Data := removeSpacesAndTabs(rest[:endIndex]) | ||
144 | - p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data))) | ||
145 | - n, err := base64.StdEncoding.Decode(p.Bytes, base64Data) | ||
146 | - if err != nil { | ||
147 | - return decodeError(data, rest) | ||
148 | - } | ||
149 | - p.Bytes = p.Bytes[:n] | ||
150 | + // After the "-----" of the ending line, there should be the same type | ||
151 | + // and then a final five dashes. | ||
152 | + endTrailer := rest[endTrailerIndex:] | ||
153 | + endTrailerLen := len(typeLine) + len(pemEndOfLine) | ||
154 | + if len(endTrailer) < endTrailerLen { | ||
155 | + continue | ||
156 | + } | ||
157 | + | ||
158 | + restOfEndLine := endTrailer[endTrailerLen:] | ||
159 | + endTrailer = endTrailer[:endTrailerLen] | ||
160 | + if !bytes.HasPrefix(endTrailer, typeLine) || | ||
161 | + !bytes.HasSuffix(endTrailer, pemEndOfLine) { | ||
162 | + continue | ||
163 | + } | ||
164 | |||
165 | - // the -1 is because we might have only matched pemEnd without the | ||
166 | - // leading newline if the PEM block was empty. | ||
167 | - _, rest = getLine(rest[endIndex+len(pemEnd)-1:]) | ||
168 | + // The line must end with only whitespace. | ||
169 | + if s, _ := getLine(restOfEndLine); len(s) != 0 { | ||
170 | + continue | ||
171 | + } | ||
172 | |||
173 | - return | ||
174 | -} | ||
175 | + base64Data := removeSpacesAndTabs(rest[:endIndex]) | ||
176 | + p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data))) | ||
177 | + n, err := base64.StdEncoding.Decode(p.Bytes, base64Data) | ||
178 | + if err != nil { | ||
179 | + continue | ||
180 | + } | ||
181 | + p.Bytes = p.Bytes[:n] | ||
182 | |||
183 | -func decodeError(data, rest []byte) (*Block, []byte) { | ||
184 | - // If we get here then we have rejected a likely looking, but | ||
185 | - // ultimately invalid PEM block. We need to start over from a new | ||
186 | - // position. We have consumed the preamble line and will have consumed | ||
187 | - // any lines which could be header lines. However, a valid preamble | ||
188 | - // line is not a valid header line, therefore we cannot have consumed | ||
189 | - // the preamble line for the any subsequent block. Thus, we will always | ||
190 | - // find any valid block, no matter what bytes precede it. | ||
191 | - // | ||
192 | - // For example, if the input is | ||
193 | - // | ||
194 | - // -----BEGIN MALFORMED BLOCK----- | ||
195 | - // junk that may look like header lines | ||
196 | - // or data lines, but no END line | ||
197 | - // | ||
198 | - // -----BEGIN ACTUAL BLOCK----- | ||
199 | - // realdata | ||
200 | - // -----END ACTUAL BLOCK----- | ||
201 | - // | ||
202 | - // we've failed to parse using the first BEGIN line | ||
203 | - // and now will try again, using the second BEGIN line. | ||
204 | - p, rest := Decode(rest) | ||
205 | - if p == nil { | ||
206 | - rest = data | ||
207 | + // the -1 is because we might have only matched pemEnd without the | ||
208 | + // leading newline if the PEM block was empty. | ||
209 | + _, rest = getLine(rest[endIndex+len(pemEnd)-1:]) | ||
210 | + return p, rest | ||
211 | } | ||
212 | - return p, rest | ||
213 | } | ||
214 | |||
215 | const pemLineLength = 64 | ||
216 | diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go | ||
217 | index 8515b46..4485581 100644 | ||
218 | --- a/src/encoding/pem/pem_test.go | ||
219 | +++ b/src/encoding/pem/pem_test.go | ||
220 | @@ -107,6 +107,12 @@ const pemMissingEndingSpace = ` | ||
221 | dGVzdA== | ||
222 | -----ENDBAR-----` | ||
223 | |||
224 | +const pemMissingEndLine = ` | ||
225 | +-----BEGIN FOO----- | ||
226 | +Header: 1` | ||
227 | + | ||
228 | +var pemRepeatingBegin = strings.Repeat("-----BEGIN \n", 10) | ||
229 | + | ||
230 | var badPEMTests = []struct { | ||
231 | name string | ||
232 | input string | ||
233 | @@ -131,14 +137,34 @@ var badPEMTests = []struct { | ||
234 | "missing ending space", | ||
235 | pemMissingEndingSpace, | ||
236 | }, | ||
237 | + { | ||
238 | + "repeating begin", | ||
239 | + pemRepeatingBegin, | ||
240 | + }, | ||
241 | + { | ||
242 | + "missing end line", | ||
243 | + pemMissingEndLine, | ||
244 | + }, | ||
245 | } | ||
246 | |||
247 | func TestBadDecode(t *testing.T) { | ||
248 | for _, test := range badPEMTests { | ||
249 | - result, _ := Decode([]byte(test.input)) | ||
250 | + result, rest := Decode([]byte(test.input)) | ||
251 | if result != nil { | ||
252 | t.Errorf("unexpected success while parsing %q", test.name) | ||
253 | } | ||
254 | + if string(rest) != test.input { | ||
255 | + t.Errorf("unexpected rest: %q; want = %q", rest, test.input) | ||
256 | + } | ||
257 | + } | ||
258 | +} | ||
259 | + | ||
260 | +func TestCVE202224675(t *testing.T) { | ||
261 | + // Prior to CVE-2022-24675, this input would cause a stack overflow. | ||
262 | + input := []byte(strings.Repeat("-----BEGIN \n", 10000000)) | ||
263 | + result, rest := Decode(input) | ||
264 | + if result != nil || !reflect.DeepEqual(rest, input) { | ||
265 | + t.Errorf("Encode of %#v decoded as %#v", input, rest) | ||
266 | } | ||
267 | } | ||
268 | |||
269 | -- | ||
270 | 2.25.1 | ||
271 | |||