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 | |
| 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')
| -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 | |||
