summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHitendra Prajapati <hprajapati@mvista.com>2022-06-24 17:00:02 +0530
committerSteve Sakoman <steve@sakoman.com>2022-06-24 07:16:22 -1000
commit6625e24a6143765ce2e4e08d25e3fe021bc2cdf6 (patch)
tree031b15db9e087006ed7988de4d5b64c18187f612
parentc6f5fb5e7545636ef7948ad1562548b7b64dac35 (diff)
downloadopenembedded-core-contrib-6625e24a6143765ce2e4e08d25e3fe021bc2cdf6.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. Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-devtools/go/go-1.14.inc1
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch271
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 += "\
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 <hprajapati@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 <hprajapati@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
+