From: Hitendra Prajapati <hprajap...@mvista.com> 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.
Signed-off-by: Hitendra Prajapati <hprajap...@mvista.com> Signed-off-by: Steve Sakoman <st...@sakoman.com> --- meta/recipes-devtools/go/go-1.14.inc | 1 + .../go/go-1.14/CVE-2022-24675.patch | 271 ++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch 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 += "\ file://CVE-2022-23806.patch \ file://CVE-2022-23772.patch \ file://CVE-2021-44717.patch \ + file://CVE-2022-24675.patch \ " 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 @@ +From 1eb931d60a24501a9668e5cb4647593e19115507 Mon Sep 17 00:00:00 2001 +From: Hitendra Prajapati <hprajap...@mvista.com> +Date: Fri, 17 Jun 2022 12:22:53 +0530 +Subject: [PATCH] CVE-2022-24675 + +Upstream-Status: Backport [https://go-review.googlesource.com/c/go/+/399816/] +CVE: CVE-2022-24675 +Signed-off-by: Hitendra Prajapati <hprajap...@mvista.com> +--- + src/encoding/pem/pem.go | 174 +++++++++++++++-------------------- + src/encoding/pem/pem_test.go | 28 +++++- + 2 files changed, 101 insertions(+), 101 deletions(-) + +diff --git a/src/encoding/pem/pem.go b/src/encoding/pem/pem.go +index a7272da..1bee1c1 100644 +--- a/src/encoding/pem/pem.go ++++ b/src/encoding/pem/pem.go +@@ -87,123 +87,97 @@ func Decode(data []byte) (p *Block, rest []byte) { + // pemStart begins with a newline. However, at the very beginning of + // the byte array, we'll accept the start string without it. + rest = data +- if bytes.HasPrefix(data, pemStart[1:]) { +- rest = rest[len(pemStart)-1 : len(data)] +- } else if i := bytes.Index(data, pemStart); i >= 0 { +- rest = rest[i+len(pemStart) : len(data)] +- } else { +- return nil, data +- } +- +- typeLine, rest := getLine(rest) +- if !bytes.HasSuffix(typeLine, pemEndOfLine) { +- return decodeError(data, rest) +- } +- typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)] +- +- p = &Block{ +- Headers: make(map[string]string), +- Type: string(typeLine), +- } +- + for { +- // This loop terminates because getLine's second result is +- // always smaller than its argument. +- if len(rest) == 0 { ++ if bytes.HasPrefix(rest, pemStart[1:]) { ++ rest = rest[len(pemStart)-1:] ++ } else if i := bytes.Index(rest, pemStart); i >= 0 { ++ rest = rest[i+len(pemStart) : len(rest)] ++ } else { + return nil, data + } +- line, next := getLine(rest) + +- i := bytes.IndexByte(line, ':') +- if i == -1 { +- break ++ var typeLine []byte ++ typeLine, rest = getLine(rest) ++ if !bytes.HasSuffix(typeLine, pemEndOfLine) { ++ continue + } ++ typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)] + +- // TODO(agl): need to cope with values that spread across lines. +- key, val := line[:i], line[i+1:] +- key = bytes.TrimSpace(key) +- val = bytes.TrimSpace(val) +- p.Headers[string(key)] = string(val) +- rest = next +- } ++ p = &Block{ ++ Headers: make(map[string]string), ++ Type: string(typeLine), ++ } + +- var endIndex, endTrailerIndex int ++ for { ++ // This loop terminates because getLine's second result is ++ // always smaller than its argument. ++ if len(rest) == 0 { ++ return nil, data ++ } ++ line, next := getLine(rest) + +- // If there were no headers, the END line might occur +- // immediately, without a leading newline. +- if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) { +- endIndex = 0 +- endTrailerIndex = len(pemEnd) - 1 +- } else { +- endIndex = bytes.Index(rest, pemEnd) +- endTrailerIndex = endIndex + len(pemEnd) +- } ++ i := bytes.IndexByte(line, ':') ++ if i == -1 { ++ break ++ } + +- if endIndex < 0 { +- return decodeError(data, rest) +- } ++ // TODO(agl): need to cope with values that spread across lines. ++ key, val := line[:i], line[i+1:] ++ key = bytes.TrimSpace(key) ++ val = bytes.TrimSpace(val) ++ p.Headers[string(key)] = string(val) ++ rest = next ++ } + +- // After the "-----" of the ending line, there should be the same type +- // and then a final five dashes. +- endTrailer := rest[endTrailerIndex:] +- endTrailerLen := len(typeLine) + len(pemEndOfLine) +- if len(endTrailer) < endTrailerLen { +- return decodeError(data, rest) +- } ++ var endIndex, endTrailerIndex int + +- restOfEndLine := endTrailer[endTrailerLen:] +- endTrailer = endTrailer[:endTrailerLen] +- if !bytes.HasPrefix(endTrailer, typeLine) || +- !bytes.HasSuffix(endTrailer, pemEndOfLine) { +- return decodeError(data, rest) +- } ++ // If there were no headers, the END line might occur ++ // immediately, without a leading newline. ++ if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) { ++ endIndex = 0 ++ endTrailerIndex = len(pemEnd) - 1 ++ } else { ++ endIndex = bytes.Index(rest, pemEnd) ++ endTrailerIndex = endIndex + len(pemEnd) ++ } + +- // The line must end with only whitespace. +- if s, _ := getLine(restOfEndLine); len(s) != 0 { +- return decodeError(data, rest) +- } ++ if endIndex < 0 { ++ continue ++ } + +- base64Data := removeSpacesAndTabs(rest[:endIndex]) +- p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data))) +- n, err := base64.StdEncoding.Decode(p.Bytes, base64Data) +- if err != nil { +- return decodeError(data, rest) +- } +- p.Bytes = p.Bytes[:n] ++ // After the "-----" of the ending line, there should be the same type ++ // and then a final five dashes. ++ endTrailer := rest[endTrailerIndex:] ++ endTrailerLen := len(typeLine) + len(pemEndOfLine) ++ if len(endTrailer) < endTrailerLen { ++ continue ++ } ++ ++ restOfEndLine := endTrailer[endTrailerLen:] ++ endTrailer = endTrailer[:endTrailerLen] ++ if !bytes.HasPrefix(endTrailer, typeLine) || ++ !bytes.HasSuffix(endTrailer, pemEndOfLine) { ++ continue ++ } + +- // the -1 is because we might have only matched pemEnd without the +- // leading newline if the PEM block was empty. +- _, rest = getLine(rest[endIndex+len(pemEnd)-1:]) ++ // The line must end with only whitespace. ++ if s, _ := getLine(restOfEndLine); len(s) != 0 { ++ continue ++ } + +- return +-} ++ base64Data := removeSpacesAndTabs(rest[:endIndex]) ++ p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data))) ++ n, err := base64.StdEncoding.Decode(p.Bytes, base64Data) ++ if err != nil { ++ continue ++ } ++ p.Bytes = p.Bytes[:n] + +-func decodeError(data, rest []byte) (*Block, []byte) { +- // If we get here then we have rejected a likely looking, but +- // ultimately invalid PEM block. We need to start over from a new +- // position. We have consumed the preamble line and will have consumed +- // any lines which could be header lines. However, a valid preamble +- // line is not a valid header line, therefore we cannot have consumed +- // the preamble line for the any subsequent block. Thus, we will always +- // find any valid block, no matter what bytes precede it. +- // +- // For example, if the input is +- // +- // -----BEGIN MALFORMED BLOCK----- +- // junk that may look like header lines +- // or data lines, but no END line +- // +- // -----BEGIN ACTUAL BLOCK----- +- // realdata +- // -----END ACTUAL BLOCK----- +- // +- // we've failed to parse using the first BEGIN line +- // and now will try again, using the second BEGIN line. +- p, rest := Decode(rest) +- if p == nil { +- rest = data ++ // the -1 is because we might have only matched pemEnd without the ++ // leading newline if the PEM block was empty. ++ _, rest = getLine(rest[endIndex+len(pemEnd)-1:]) ++ return p, rest + } +- return p, rest + } + + const pemLineLength = 64 +diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go +index 8515b46..4485581 100644 +--- a/src/encoding/pem/pem_test.go ++++ b/src/encoding/pem/pem_test.go +@@ -107,6 +107,12 @@ const pemMissingEndingSpace = ` + dGVzdA== + -----ENDBAR-----` + ++const pemMissingEndLine = ` ++-----BEGIN FOO----- ++Header: 1` ++ ++var pemRepeatingBegin = strings.Repeat("-----BEGIN \n", 10) ++ + var badPEMTests = []struct { + name string + input string +@@ -131,14 +137,34 @@ var badPEMTests = []struct { + "missing ending space", + pemMissingEndingSpace, + }, ++ { ++ "repeating begin", ++ pemRepeatingBegin, ++ }, ++ { ++ "missing end line", ++ pemMissingEndLine, ++ }, + } + + func TestBadDecode(t *testing.T) { + for _, test := range badPEMTests { +- result, _ := Decode([]byte(test.input)) ++ result, rest := Decode([]byte(test.input)) + if result != nil { + t.Errorf("unexpected success while parsing %q", test.name) + } ++ if string(rest) != test.input { ++ t.Errorf("unexpected rest: %q; want = %q", rest, test.input) ++ } ++ } ++} ++ ++func TestCVE202224675(t *testing.T) { ++ // Prior to CVE-2022-24675, this input would cause a stack overflow. ++ input := []byte(strings.Repeat("-----BEGIN \n", 10000000)) ++ result, rest := Decode(input) ++ if result != nil || !reflect.DeepEqual(rest, input) { ++ t.Errorf("Encode of %#v decoded as %#v", input, rest) + } + } + +-- +2.25.1 + -- 2.25.1
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#167417): https://lists.openembedded.org/g/openembedded-core/message/167417 Mute This Topic: https://lists.openembedded.org/mt/92090257/21656 Group Owner: openembedded-core+ow...@lists.openembedded.org Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-