From 480c37a7cd59daee40533b2401de1ac447560df8 Mon Sep 17 00:00:00 2001 From: hanchao Date: Wed, 11 May 2022 10:39:20 +0800 Subject: [PATCH 1/7] fix CVE-2022-28327,CVE-2022-24675 Conflict: NA Score: CVE-2022-28327:7.5,CVE-2022-24675:7.5 Reference: https://go-review.googlesource.com/c/go/+/397136,https://go-review.googlesource.com/c/go/+/399816 Reason: CVE-2022-28327,CVE-2022-24675 (cherry picked from commit 11457185219bd14f1bf975780e3ee066342ab9cb) --- ...o1.17-crypto-elliptic-tolerate-zero-.patch | 60 ++++ ...o1.17-encoding-pem-fix-stack-overflo.patch | 291 ++++++++++++++++++ golang.spec | 59 +--- 3 files changed, 362 insertions(+), 48 deletions(-) create mode 100644 0001-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch create mode 100644 0002-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch diff --git a/0001-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch b/0001-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch new file mode 100644 index 0000000..6f993e0 --- /dev/null +++ b/0001-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch @@ -0,0 +1,60 @@ +From ad33fdc8f4bce612842d922ca701c3062fe4d4c6 Mon Sep 17 00:00:00 2001 +From: Filippo Valsorda +Date: Thu, 31 Mar 2022 12:31:58 -0400 +Subject: [Backport 1/2] [release-branch.go1.17] crypto/elliptic: tolerate + zero-padded scalars in generic P-256 + +Updates #52075 +Fixes #52076 +Fixes CVE-2022-28327 + +Change-Id: I595a7514c9a0aa1b9c76aedfc2307e1124271f27 +Reviewed-on: https://go-review.googlesource.com/c/go/+/397136 +Trust: Filippo Valsorda +Reviewed-by: Julie Qiu + +Conflict:NA +Reference:https://go-review.googlesource.com/c/go/+/399816,https://go-review.googlesource.com/c/go/+/397136 +--- + src/crypto/elliptic/p256.go | 2 +- + src/crypto/elliptic/p256_test.go | 14 ++++++++++++++ + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go +index b2b12c8f13..da5283735c 100644 +--- a/src/crypto/elliptic/p256.go ++++ b/src/crypto/elliptic/p256.go +@@ -52,7 +52,7 @@ func p256GetScalar(out *[32]byte, in []byte) { + n := new(big.Int).SetBytes(in) + var scalarBytes []byte + +- if n.Cmp(p256Params.N) >= 0 { ++ if n.Cmp(p256Params.N) >= 0 || len(in) > len(out) { + n.Mod(n, p256Params.N) + scalarBytes = n.Bytes() + } else { +diff --git a/src/crypto/elliptic/p256_test.go b/src/crypto/elliptic/p256_test.go +index 1435f5e1a5..694186df81 100644 +--- a/src/crypto/elliptic/p256_test.go ++++ b/src/crypto/elliptic/p256_test.go +@@ -153,3 +153,17 @@ func TestP256CombinedMult(t *testing.T) { + t.Errorf("1×G + (-1)×G = (%d, %d), should be ∞", x, y) + } + } ++ ++func TestIssue52075(t *testing.T) { ++ Gx, Gy := P256().Params().Gx, P256().Params().Gy ++ scalar := make([]byte, 33) ++ scalar[32] = 1 ++ x, y := P256().ScalarBaseMult(scalar) ++ if x.Cmp(Gx) != 0 || y.Cmp(Gy) != 0 { ++ t.Errorf("unexpected output (%v,%v)", x, y) ++ } ++ x, y = P256().ScalarMult(Gx, Gy, scalar) ++ if x.Cmp(Gx) != 0 || y.Cmp(Gy) != 0 { ++ t.Errorf("unexpected output (%v,%v)", x, y) ++ } ++} +-- +2.30.0 + diff --git a/0002-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch b/0002-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch new file mode 100644 index 0000000..243596c --- /dev/null +++ b/0002-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch @@ -0,0 +1,291 @@ +From baaaf3ce29bf98efc00c2f06c531f2b0186b027b Mon Sep 17 00:00:00 2001 +From: Julie Qiu +Date: Tue, 1 Mar 2022 10:19:38 -0600 +Subject: [Backport 2/2] [release-branch.go1.17] encoding/pem: fix stack + overflow in Decode + +Previously, Decode called decodeError, a recursive function that was +prone to stack overflows when given a large PEM file containing errors. + +Credit to Juho Nurminen of Mattermost who reported the error. + +Fixes CVE-2022-24675 +Updates #51853 +Fixes #52036 + +Change-Id: Iffe768be53c8ddc0036fea0671d290f8f797692c +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1391157 +Reviewed-by: Damien Neil +Reviewed-by: Filippo Valsorda +(cherry picked from commit 794ea5e828010e8b68493b2fc6d2963263195a02) +Reviewed-on: https://go-review.googlesource.com/c/go/+/399816 +Run-TryBot: Dmitri Shuralyov +Reviewed-by: Dmitri Shuralyov +Reviewed-by: Cherry Mui +TryBot-Result: Gopher Robot + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/399816 +--- + 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 a7272da5ad..1bee1c12d2 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 b2b6b15e73..c94b5ca53b 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.30.0 + diff --git a/golang.spec b/golang.spec index 11cc5e2..cb23b1a 100644 --- a/golang.spec +++ b/golang.spec @@ -66,7 +66,7 @@ Name: golang Version: 1.17.3 -Release: 1 +Release: 2 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -153,9 +153,10 @@ Obsoletes: %{name}-vim < 1.4 Obsoletes: emacs-%{name} < 1.4 Requires: openEuler-rpm-config -ExclusiveArch: %{golang_arches} - +Patch6001: 0001-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch +Patch6002: 0002-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch +ExclusiveArch: %{golang_arches} %description %{summary}. @@ -388,50 +389,12 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Fri May 6 2022 hanchao - 1.17.3-2 +- Type:CVE +- CVE:CVE-2022-28327,CVE-2022-24675 +- SUG:NA +- DESC:fix CVE-2022-28327,CVE-2022-24675 +- fix CVE-2022-28327 CVE-2022-24675 + * Mon Nov 29 2021 chenjiankun - 1.17.3-1 - upgrade to 1.17.3 - -* Thu Apr 15 2021 lixiang - 1.15.7-2 -- speed up build progress - -* Thu Jan 28 2021 xingweizheng - 1.15.7-1 -- upgrade to 1.15.7 - -* Mon Dec 7 2020 yangyanchao - 1.15.5-3 -- Enable Cgo for RISC-V - -* Sat Nov 28 2020 whoisxxx - 1.15.5-2 -- Adate for RISC-V - -* Wed Nov 18 2020 liuzekun - 1.15.5-1 -- upgrade to 1.15.5 - -* Tue Aug 18 2020 xiadanni - 1.13.15-1 -- upgrade to 1.13.15 - -* Fri Jul 31 2020 xiadanni - 1.13.14-2 -- add yaml file - -* Thu Jul 30 2020 xiadanni - 1.13.14-1 -- upgrade to 1.13.14 - -* Thu Jul 23 2020 xiadanni - 1.13-4.1 -- bump to 1.13.4 - -* Tue May 12 2020 lixiang - 1.13-3.6 -- rename tar name and make it same with upstream - -* Tue Mar 24 2020 jingrui - 1.13-3.5 -- drop hard code cert - -* Mon Mar 23 2020 jingrui - 1.13-3.4 -- fix CVE-2020-7919 - -* Thu Feb 20 2020 openEuler Buildteam - 1.13-3.2 -- requires remove mercurial - -* Tue Dec 10 2019 jingrui - 1.13-3.1 -- upgrade to golang 1.13.3 - -* Tue Sep 03 2019 leizhongkai - 1.11-1 -- backport fix CVE-2019-9512 and CVE-2019-9514 -- Gitee From 18b3b14062de600a7dc35264f03232775b4a14bd Mon Sep 17 00:00:00 2001 From: hanchao Date: Mon, 16 May 2022 15:29:26 +0800 Subject: [PATCH 2/7] fix CVE-2021-44717 Conflict: NA Score: 4.8 Reference: https://go-review.googlesource.com/c/go/+/370534 Reason: fix CVE-2021-44717 Signed-off-by: hanchao (cherry picked from commit 6f993c149e73653dae13ace07e524c29878dcea3) --- ...o1.17-syscall-fix-ForkLock-spurious-.patch | 79 +++++++++++++++++++ golang.spec | 10 ++- 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 0003-release-branch.go1.17-syscall-fix-ForkLock-spurious-.patch diff --git a/0003-release-branch.go1.17-syscall-fix-ForkLock-spurious-.patch b/0003-release-branch.go1.17-syscall-fix-ForkLock-spurious-.patch new file mode 100644 index 0000000..64aee69 --- /dev/null +++ b/0003-release-branch.go1.17-syscall-fix-ForkLock-spurious-.patch @@ -0,0 +1,79 @@ +From e7aab832069d06d77e04a585803dfdb04453253a Mon Sep 17 00:00:00 2001 +From: Russ Cox +Date: Wed, 8 Dec 2021 18:05:11 -0500 +Subject: [PATCH] [release-branch.go1.17] syscall: fix ForkLock spurious + close(0) on pipe failure + +Pipe (and therefore forkLockPipe) does not make any guarantees +about the state of p after a failed Pipe(p). Avoid that assumption +and the too-clever goto, so that we don't accidentally Close a real fd +if the failed pipe leaves p[0] or p[1] set >= 0. + +Updates #50057 +Fixes CVE-2021-44717 + +Change-Id: Iff8e19a6efbba0c73cc8b13ecfae381c87600bb4 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1291270 +Reviewed-by: Ian Lance Taylor +Reviewed-on: https://go-review.googlesource.com/c/go/+/370534 +Trust: Filippo Valsorda +Run-TryBot: Filippo Valsorda +TryBot-Result: Gopher Robot +Reviewed-by: Alex Rakoczy +--- + src/syscall/exec_unix.go | 20 ++++++-------------- + 1 file changed, 6 insertions(+), 14 deletions(-) + +diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go +index 54b18dccd7..c9c9d1abf3 100644 +--- a/src/syscall/exec_unix.go ++++ b/src/syscall/exec_unix.go +@@ -153,9 +153,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) + sys = &zeroSysProcAttr + } + +- p[0] = -1 +- p[1] = -1 +- + // Convert args to C form. + argv0p, err := BytePtrFromString(argv0) + if err != nil { +@@ -205,14 +202,17 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) + + // Allocate child status pipe close on exec. + if err = forkExecPipe(p[:]); err != nil { +- goto error ++ ForkLock.Unlock() ++ return 0, err + } + + // Kick off child. + pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1]) + if err1 != 0 { +- err = Errno(err1) +- goto error ++ Close(p[0]) ++ Close(p[1]) ++ ForkLock.Unlock() ++ return 0, Errno(err1) + } + ForkLock.Unlock() + +@@ -244,14 +244,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) + + // Read got EOF, so pipe closed on exec, so exec succeeded. + return pid, nil +- +-error: +- if p[0] >= 0 { +- Close(p[0]) +- Close(p[1]) +- } +- ForkLock.Unlock() +- return 0, err + } + + // Combination of fork and exec, careful to be thread safe. +-- +2.30.0 + diff --git a/golang.spec b/golang.spec index cb23b1a..2e4a58c 100644 --- a/golang.spec +++ b/golang.spec @@ -66,7 +66,7 @@ Name: golang Version: 1.17.3 -Release: 2 +Release: 3 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -155,6 +155,7 @@ Requires: openEuler-rpm-config Patch6001: 0001-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch Patch6002: 0002-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch +Patch6003: 0003-release-branch.go1.17-syscall-fix-ForkLock-spurious-.patch ExclusiveArch: %{golang_arches} @@ -389,6 +390,13 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Fri May 6 2022 hanchao - 1.17.3-2 +- Type:CVE +- CVE:CVE-2021-44717 +- SUG:NA +- DESC:fix CVE-2021-44717 +- fix CVE-2021-44717 + * Fri May 6 2022 hanchao - 1.17.3-2 - Type:CVE - CVE:CVE-2022-28327,CVE-2022-24675 -- Gitee From 5074a7640fb256937f1d63126c091bea71ae2499 Mon Sep 17 00:00:00 2001 From: hc Date: Mon, 16 May 2022 07:56:24 +0000 Subject: [PATCH 3/7] update golang.spec. (cherry picked from commit 9ab15eb485c326d714d62ddf7518644149460885) --- golang.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golang.spec b/golang.spec index 2e4a58c..597c7e6 100644 --- a/golang.spec +++ b/golang.spec @@ -390,7 +390,7 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog -* Fri May 6 2022 hanchao - 1.17.3-2 +* Fri May 6 2022 hanchao - 1.17.3-3 - Type:CVE - CVE:CVE-2021-44717 - SUG:NA -- Gitee From d396cae1ba40462f1341434c326101754b950ae5 Mon Sep 17 00:00:00 2001 From: hubin Date: Tue, 28 Jun 2022 19:16:14 +0800 Subject: [PATCH 4/7] backport patch to fix bug of golang plugin mode Signed-off-by: hubin (cherry picked from commit e40a694498d46d2be02ce1add6a14d5d1fdf6987) --- ...-mark-unexported-methods-for-plugins.patch | 39 +++++++++++++++++++ golang.spec | 9 ++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 0004-backport-cmd-link-mark-unexported-methods-for-plugins.patch diff --git a/0004-backport-cmd-link-mark-unexported-methods-for-plugins.patch b/0004-backport-cmd-link-mark-unexported-methods-for-plugins.patch new file mode 100644 index 0000000..6b9dd4b --- /dev/null +++ b/0004-backport-cmd-link-mark-unexported-methods-for-plugins.patch @@ -0,0 +1,39 @@ +From c872b0594f716a2a0799b07d7226a45f02c005f1 Mon Sep 17 00:00:00 2001 +From: Cherry Mui +Date: Wed, 16 Mar 2022 13:07:57 -0400 +Subject: [PATCH] cmd/link: mark unexported methods for plugins + +When plugin is used, we already mark all exported methods +reachable. However, when the plugin and the host program share +a common package, an unexported method could also be reachable +from both the plugin and the host via interfaces. We need to mark +them as well. + +Fixes #51621. + +Change-Id: I1a70d3f96b66b803f2d0ab14d00ed0df276ea500 +Reviewed-on: https://go-review.googlesource.com/c/go/+/393365 +Trust: Cherry Mui +Run-TryBot: Cherry Mui +TryBot-Result: Gopher Robot +Reviewed-by: Than McIntosh +--- + src/cmd/link/internal/ld/deadcode.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go +index e4fa75f..21a9703 100644 +--- a/src/cmd/link/internal/ld/deadcode.go ++++ b/src/cmd/link/internal/ld/deadcode.go +@@ -350,7 +350,7 @@ func deadcode(ctxt *Link) { + // in the last pass. + rem := d.markableMethods[:0] + for _, m := range d.markableMethods { +- if (d.reflectSeen && m.isExported()) || d.ifaceMethod[m.m] { ++ if (d.reflectSeen && (m.isExported() || d.dynlink)) || d.ifaceMethod[m.m] { + d.markMethod(m) + } else { + rem = append(rem, m) +-- +1.8.3.1 + diff --git a/golang.spec b/golang.spec index 597c7e6..f28b764 100644 --- a/golang.spec +++ b/golang.spec @@ -66,7 +66,7 @@ Name: golang Version: 1.17.3 -Release: 3 +Release: 4 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -156,6 +156,7 @@ Requires: openEuler-rpm-config Patch6001: 0001-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch Patch6002: 0002-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch Patch6003: 0003-release-branch.go1.17-syscall-fix-ForkLock-spurious-.patch +Patch6004: 0004-backport-cmd-link-mark-unexported-methods-for-plugins.patch ExclusiveArch: %{golang_arches} @@ -390,6 +391,12 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Tue Jun 28 2022 Bin Hu - 1.17.3-4 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:backport patch to fix bug of golang plugin mode + * Fri May 6 2022 hanchao - 1.17.3-3 - Type:CVE - CVE:CVE-2021-44717 -- Gitee From 91e897978667031493760b54e4fe1455570eb862 Mon Sep 17 00:00:00 2001 From: hanchao Date: Tue, 26 Jul 2022 21:13:25 +0800 Subject: [PATCH 5/7] golang: fix CVE-2022-32148,CVE-2022-1962,CVE-2022-1705,CVE-2022-30633, CVE-2022-30635,CVE-2022-30630,CVE-2022-30632,CVE-2022-28131, CVE-2022-30631,CVE-2022-30629,CVE-2022-30634 Conflict: NA Score: CVE-2022-32148: 5.3 CVE-2022-1962: 6.2 CVE-2022-1705: 5.3 CVE-2022-30633: 6.2 CVE-2022-30635: 5.5 CVE-2022-30630: 6.2 CVE-2022-30632: 6.2 CVE-2022-28131: 6.2 CVE-2022-30631: 7.5 CVE-2022-30629: 2.6 CVE-2022-30634: 7.5 Reference: CVE-2022-32148: https://go-review.googlesource.com/c/go/+/415221 CVE-2022-1962: https://go-review.googlesource.com/c/go/+/417070 CVE-2022-1705: https://go-review.googlesource.com/c/go/+/415217 CVE-2022-30633: https://go-review.googlesource.com/c/go/+/417069 CVE-2022-30635: https://go-review.googlesource.com/c/go/+/417074 CVE-2022-30630: https://go-review.googlesource.com/c/go/+/417072 CVE-2022-30632: https://go-review.googlesource.com/c/go/+/417073 CVE-2022-28131: https://go-review.googlesource.com/c/go/+/417068 CVE-2022-30631: https://go-review.googlesource.com/c/go/+/417071 CVE-2022-30629: https://go-review.googlesource.com/c/go/+/408574 CVE-2022-30634: https://go-review.googlesource.com/c/go/+/406635 Reason: fix CVE: CVE-2022-32148: 0005-release-branch.go1.17-net-http-preserve-nil-values-i.patch CVE-2022-1962: 0006-release-branch.go1.17-go-parser-limit-recursion-dept.patch CVE-2022-1705: 0007-release-branch.go1.17-net-http-don-t-strip-whitespac.patch CVE-2022-30633: 0008-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch CVE-2022-30635: 0009-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch CVE-2022-30630: 0010-release-branch.go1.17-io-fs-fix-stack-exhaustion-in-.patch CVE-2022-30632: 0011-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch CVE-2022-28131: 0012-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch CVE-2022-30631: 0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch CVE-2022-30629: 0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch CVE-2022-30634: 0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch (cherry picked from commit 40c91388a14ffca6efc7fc085165dece753b6da8) --- ...o1.17-net-http-preserve-nil-values-i.patch | 70 +++ ...o1.17-go-parser-limit-recursion-dept.patch | 421 ++++++++++++++++++ ...o1.17-net-http-don-t-strip-whitespac.patch | 62 +++ ...o1.17-encoding-xml-limit-depth-of-ne.patch | 168 +++++++ ...o1.17-encoding-gob-add-a-depth-limit.patch | 138 ++++++ ...o1.17-io-fs-fix-stack-exhaustion-in-.patch | 96 ++++ ...o1.17-path-filepath-fix-stack-exhaus.patch | 85 ++++ ...o1.17-encoding-xml-use-iterative-Ski.patch | 69 +++ ...o1.17-compress-gzip-fix-stack-exhaus.patch | 133 ++++++ ...o1.17-crypto-tls-randomly-generate-t.patch | 69 +++ ...o1.17-crypto-rand-properly-handle-la.patch | 246 ++++++++++ golang.spec | 21 +- 12 files changed, 1577 insertions(+), 1 deletion(-) create mode 100644 0005-release-branch.go1.17-net-http-preserve-nil-values-i.patch create mode 100644 0006-release-branch.go1.17-go-parser-limit-recursion-dept.patch create mode 100644 0007-release-branch.go1.17-net-http-don-t-strip-whitespac.patch create mode 100644 0008-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch create mode 100644 0009-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch create mode 100644 0010-release-branch.go1.17-io-fs-fix-stack-exhaustion-in-.patch create mode 100644 0011-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch create mode 100644 0012-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch create mode 100644 0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch create mode 100644 0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch create mode 100644 0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch diff --git a/0005-release-branch.go1.17-net-http-preserve-nil-values-i.patch b/0005-release-branch.go1.17-net-http-preserve-nil-values-i.patch new file mode 100644 index 0000000..9897234 --- /dev/null +++ b/0005-release-branch.go1.17-net-http-preserve-nil-values-i.patch @@ -0,0 +1,70 @@ +From 67bff2eb995a098f838fa4b799c0b8261292e6e7 Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Fri, 17 Jun 2022 10:09:45 -0700 +Subject: [PATCH 01/11] [release-branch.go1.17] net/http: preserve nil values + in Header.Clone + +ReverseProxy makes a distinction between nil and zero-length header values. +Avoid losing nil-ness when cloning a request. + +Thanks to Christian Mehlmauer for discovering this. + +For #53423 +For CVE-2022-32148 +Fixes #53620 + +Change-Id: Ice369cdb4712e2d62e25bb881b080847aa4801f5 +Reviewed-on: https://go-review.googlesource.com/c/go/+/412857 +Reviewed-by: Ian Lance Taylor +Reviewed-by: Brad Fitzpatrick +(cherry picked from commit b2cc0fecc2ccd80e6d5d16542cc684f97b3a9c8a) +Reviewed-on: https://go-review.googlesource.com/c/go/+/415221 +Reviewed-by: Heschi Kreinick +TryBot-Result: Gopher Robot +Run-TryBot: Michael Knyszek +Run-TryBot: Heschi Kreinick +Reviewed-by: Michael Knyszek + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/415221 +--- + src/net/http/header.go | 6 ++++++ + src/net/http/header_test.go | 5 +++++ + 2 files changed, 11 insertions(+) + +diff --git a/src/net/http/header.go b/src/net/http/header.go +index 4c72dcb2c88..ef4ee7ffa81 100644 +--- a/src/net/http/header.go ++++ b/src/net/http/header.go +@@ -101,6 +101,12 @@ func (h Header) Clone() Header { + sv := make([]string, nv) // shared backing array for headers' values + h2 := make(Header, len(h)) + for k, vv := range h { ++ if vv == nil { ++ // Preserve nil values. ReverseProxy distinguishes ++ // between nil and zero-length header values. ++ h2[k] = nil ++ continue ++ } + n := copy(sv, vv) + h2[k] = sv[:n:n] + sv = sv[n:] +diff --git a/src/net/http/header_test.go b/src/net/http/header_test.go +index 47893629194..80c003551db 100644 +--- a/src/net/http/header_test.go ++++ b/src/net/http/header_test.go +@@ -235,6 +235,11 @@ func TestCloneOrMakeHeader(t *testing.T) { + in: Header{"foo": {"bar"}}, + want: Header{"foo": {"bar"}}, + }, ++ { ++ name: "nil value", ++ in: Header{"foo": nil}, ++ want: Header{"foo": nil}, ++ }, + } + + for _, tt := range tests { +-- +2.30.2 + diff --git a/0006-release-branch.go1.17-go-parser-limit-recursion-dept.patch b/0006-release-branch.go1.17-go-parser-limit-recursion-dept.patch new file mode 100644 index 0000000..23a903a --- /dev/null +++ b/0006-release-branch.go1.17-go-parser-limit-recursion-dept.patch @@ -0,0 +1,421 @@ +From b78e521644334294019da243a5ff57436f70cd72 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Wed, 15 Jun 2022 10:43:05 -0700 +Subject: [PATCH 02/11] [release-branch.go1.17] go/parser: limit recursion + depth + +Limit nested parsing to 100,000, which prevents stack exhaustion when +parsing deeply nested statements, types, and expressions. Also limit +the scope depth to 1,000 during object resolution. + +Thanks to Juho Nurminen of Mattermost for reporting this issue. + +Fixes #53707 +Updates #53616 +Fixes CVE-2022-1962 + +Change-Id: I4d7b86c1d75d0bf3c7af1fdea91582aa74272c64 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1491025 +Reviewed-by: Russ Cox +Reviewed-by: Damien Neil +(cherry picked from commit 6a856f08d58e4b6705c0c337d461c540c1235c83) +Reviewed-on: https://go-review.googlesource.com/c/go/+/417070 +Reviewed-by: Heschi Kreinick +TryBot-Result: Gopher Robot +Run-TryBot: Michael Knyszek + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/417070 +--- + src/go/parser/interface.go | 10 ++- + src/go/parser/parser.go | 54 ++++++++++- + src/go/parser/parser_test.go | 169 +++++++++++++++++++++++++++++++++++ + src/go/parser/resolver.go | 9 ++ + 4 files changed, 236 insertions(+), 6 deletions(-) + +diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go +index 85486d2f4b4..eae429e6ef3 100644 +--- a/src/go/parser/interface.go ++++ b/src/go/parser/interface.go +@@ -97,8 +97,11 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) + defer func() { + if e := recover(); e != nil { + // resume same panic if it's not a bailout +- if _, ok := e.(bailout); !ok { ++ bail, ok := e.(bailout) ++ if !ok { + panic(e) ++ } else if bail.msg != "" { ++ p.errors.Add(p.file.Position(bail.pos), bail.msg) + } + } + +@@ -203,8 +206,11 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M + defer func() { + if e := recover(); e != nil { + // resume same panic if it's not a bailout +- if _, ok := e.(bailout); !ok { ++ bail, ok := e.(bailout) ++ if !ok { + panic(e) ++ } else if bail.msg != "" { ++ p.errors.Add(p.file.Position(bail.pos), bail.msg) + } + } + p.errors.Sort() +diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go +index f10c8650afd..2c42b9f8cc2 100644 +--- a/src/go/parser/parser.go ++++ b/src/go/parser/parser.go +@@ -60,6 +60,10 @@ type parser struct { + inRhs bool // if set, the parser is parsing a rhs expression + + imports []*ast.ImportSpec // list of imports ++ ++ // nestLev is used to track and limit the recursion depth ++ // during parsing. ++ nestLev int + } + + func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) { +@@ -110,6 +114,24 @@ func un(p *parser) { + p.printTrace(")") + } + ++// maxNestLev is the deepest we're willing to recurse during parsing ++const maxNestLev int = 1e5 ++ ++func incNestLev(p *parser) *parser { ++ p.nestLev++ ++ if p.nestLev > maxNestLev { ++ p.error(p.pos, "exceeded max nesting depth") ++ panic(bailout{}) ++ } ++ return p ++} ++ ++// decNestLev is used to track nesting depth during parsing to prevent stack exhaustion. ++// It is used along with incNestLev in a similar fashion to how un and trace are used. ++func decNestLev(p *parser) { ++ p.nestLev-- ++} ++ + // Advance to the next token. + func (p *parser) next0() { + // Because of one-token look-ahead, print the previous token +@@ -222,8 +244,12 @@ func (p *parser) next() { + } + } + +-// A bailout panic is raised to indicate early termination. +-type bailout struct{} ++// A bailout panic is raised to indicate early termination. pos and msg are ++// only populated when bailing out of object resolution. ++type bailout struct { ++ pos token.Pos ++ msg string ++} + + func (p *parser) error(pos token.Pos, msg string) { + if p.trace { +@@ -1119,6 +1145,8 @@ func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr { + } + + func (p *parser) tryIdentOrType() ast.Expr { ++ defer decNestLev(incNestLev(p)) ++ + switch p.tok { + case token.IDENT: + typ := p.parseTypeName(nil) +@@ -1531,7 +1559,13 @@ func (p *parser) parsePrimaryExpr() (x ast.Expr) { + } + + x = p.parseOperand() +- for { ++ // We track the nesting here rather than at the entry for the function, ++ // since it can iteratively produce a nested output, and we want to ++ // limit how deep a structure we generate. ++ var n int ++ defer func() { p.nestLev -= n }() ++ for n = 1; ; n++ { ++ incNestLev(p) + switch p.tok { + case token.PERIOD: + p.next() +@@ -1591,6 +1625,8 @@ func (p *parser) parsePrimaryExpr() (x ast.Expr) { + } + + func (p *parser) parseUnaryExpr() ast.Expr { ++ defer decNestLev(incNestLev(p)) ++ + if p.trace { + defer un(trace(p, "UnaryExpr")) + } +@@ -1673,7 +1709,13 @@ func (p *parser) parseBinaryExpr(prec1 int) ast.Expr { + } + + x := p.parseUnaryExpr() +- for { ++ // We track the nesting here rather than at the entry for the function, ++ // since it can iteratively produce a nested output, and we want to ++ // limit how deep a structure we generate. ++ var n int ++ defer func() { p.nestLev -= n }() ++ for n = 1; ; n++ { ++ incNestLev(p) + op, oprec := p.tokPrec() + if oprec < prec1 { + return x +@@ -1962,6 +2004,8 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) { + } + + func (p *parser) parseIfStmt() *ast.IfStmt { ++ defer decNestLev(incNestLev(p)) ++ + if p.trace { + defer un(trace(p, "IfStmt")) + } +@@ -2265,6 +2309,8 @@ func (p *parser) parseForStmt() ast.Stmt { + } + + func (p *parser) parseStmt() (s ast.Stmt) { ++ defer decNestLev(incNestLev(p)) ++ + if p.trace { + defer un(trace(p, "Statement")) + } +diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go +index a4f882d3688..1a46c878663 100644 +--- a/src/go/parser/parser_test.go ++++ b/src/go/parser/parser_test.go +@@ -10,6 +10,7 @@ import ( + "go/ast" + "go/token" + "io/fs" ++ "runtime" + "strings" + "testing" + ) +@@ -577,3 +578,171 @@ type x int // comment + t.Errorf("got %q, want %q", comment, "// comment") + } + } ++ ++var parseDepthTests = []struct { ++ name string ++ format string ++ // multipler is used when a single statement may result in more than one ++ // change in the depth level, for instance "1+(..." produces a BinaryExpr ++ // followed by a UnaryExpr, which increments the depth twice. The test ++ // case comment explains which nodes are triggering the multiple depth ++ // changes. ++ parseMultiplier int ++ // scope is true if we should also test the statement for the resolver scope ++ // depth limit. ++ scope bool ++ // scopeMultiplier does the same as parseMultiplier, but for the scope ++ // depths. ++ scopeMultiplier int ++}{ ++ // The format expands the part inside « » many times. ++ // A second set of brackets nested inside the first stops the repetition, ++ // so that for example «(«1»)» expands to (((...((((1))))...))). ++ {name: "array", format: "package main; var x «[1]»int"}, ++ {name: "slice", format: "package main; var x «[]»int"}, ++ {name: "struct", format: "package main; var x «struct { X «int» }»", scope: true}, ++ {name: "pointer", format: "package main; var x «*»int"}, ++ {name: "func", format: "package main; var x «func()»int", scope: true}, ++ {name: "chan", format: "package main; var x «chan »int"}, ++ {name: "chan2", format: "package main; var x «<-chan »int"}, ++ {name: "interface", format: "package main; var x «interface { M() «int» }»", scope: true, scopeMultiplier: 2}, // Scopes: InterfaceType, FuncType ++ {name: "map", format: "package main; var x «map[int]»int"}, ++ {name: "slicelit", format: "package main; var x = «[]any{«»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit ++ {name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit ++ {name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit ++ {name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 2}, // Parser nodes: CompositeLit, KeyValueExpr ++ {name: "dot", format: "package main; var x = «x.»x"}, ++ {name: "index", format: "package main; var x = x«[1]»"}, ++ {name: "slice", format: "package main; var x = x«[1:2]»"}, ++ {name: "slice3", format: "package main; var x = x«[1:2:3]»"}, ++ {name: "dottype", format: "package main; var x = x«.(any)»"}, ++ {name: "callseq", format: "package main; var x = x«()»"}, ++ {name: "methseq", format: "package main; var x = x«.m()»", parseMultiplier: 2}, // Parser nodes: SelectorExpr, CallExpr ++ {name: "binary", format: "package main; var x = «1+»1"}, ++ {name: "binaryparen", format: "package main; var x = «1+(«1»)»", parseMultiplier: 2}, // Parser nodes: BinaryExpr, ParenExpr ++ {name: "unary", format: "package main; var x = «^»1"}, ++ {name: "addr", format: "package main; var x = «& »x"}, ++ {name: "star", format: "package main; var x = «*»x"}, ++ {name: "recv", format: "package main; var x = «<-»x"}, ++ {name: "call", format: "package main; var x = «f(«1»)»", parseMultiplier: 2}, // Parser nodes: Ident, CallExpr ++ {name: "conv", format: "package main; var x = «(*T)(«1»)»", parseMultiplier: 2}, // Parser nodes: ParenExpr, CallExpr ++ {name: "label", format: "package main; func main() { «Label:» }"}, ++ {name: "if", format: "package main; func main() { «if true { «» }»}", parseMultiplier: 2, scope: true, scopeMultiplier: 2}, // Parser nodes: IfStmt, BlockStmt. Scopes: IfStmt, BlockStmt ++ {name: "ifelse", format: "package main; func main() { «if true {} else » {} }", scope: true}, ++ {name: "switch", format: "package main; func main() { «switch { default: «» }»}", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause ++ {name: "typeswitch", format: "package main; func main() { «switch x.(type) { default: «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause ++ {name: "for0", format: "package main; func main() { «for { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt ++ {name: "for1", format: "package main; func main() { «for x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt ++ {name: "for3", format: "package main; func main() { «for f(); g(); h() { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt ++ {name: "forrange0", format: "package main; func main() { «for range x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt ++ {name: "forrange1", format: "package main; func main() { «for x = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt ++ {name: "forrange2", format: "package main; func main() { «for x, y = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt ++ {name: "go", format: "package main; func main() { «go func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: GoStmt, FuncLit ++ {name: "defer", format: "package main; func main() { «defer func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: DeferStmt, FuncLit ++ {name: "select", format: "package main; func main() { «select { default: «» }» }", scope: true}, ++} ++ ++// split splits pre«mid»post into pre, mid, post. ++// If the string does not have that form, split returns x, "", "". ++func split(x string) (pre, mid, post string) { ++ start, end := strings.Index(x, "«"), strings.LastIndex(x, "»") ++ if start < 0 || end < 0 { ++ return x, "", "" ++ } ++ return x[:start], x[start+len("«") : end], x[end+len("»"):] ++} ++ ++func TestParseDepthLimit(t *testing.T) { ++ if runtime.GOARCH == "wasm" { ++ t.Skip("causes call stack exhaustion on js/wasm") ++ } ++ for _, tt := range parseDepthTests { ++ for _, size := range []string{"small", "big"} { ++ t.Run(tt.name+"/"+size, func(t *testing.T) { ++ n := maxNestLev + 1 ++ if tt.parseMultiplier > 0 { ++ n /= tt.parseMultiplier ++ } ++ if size == "small" { ++ // Decrease the number of statements by 10, in order to check ++ // that we do not fail when under the limit. 10 is used to ++ // provide some wiggle room for cases where the surrounding ++ // scaffolding syntax adds some noise to the depth that changes ++ // on a per testcase basis. ++ n -= 10 ++ } ++ ++ pre, mid, post := split(tt.format) ++ if strings.Contains(mid, "«") { ++ left, base, right := split(mid) ++ mid = strings.Repeat(left, n) + base + strings.Repeat(right, n) ++ } else { ++ mid = strings.Repeat(mid, n) ++ } ++ input := pre + mid + post ++ ++ fset := token.NewFileSet() ++ _, err := ParseFile(fset, "", input, ParseComments|SkipObjectResolution) ++ if size == "small" { ++ if err != nil { ++ t.Errorf("ParseFile(...): %v (want success)", err) ++ } ++ } else { ++ expected := "exceeded max nesting depth" ++ if err == nil || !strings.HasSuffix(err.Error(), expected) { ++ t.Errorf("ParseFile(...) = _, %v, want %q", err, expected) ++ } ++ } ++ }) ++ } ++ } ++} ++ ++func TestScopeDepthLimit(t *testing.T) { ++ if runtime.GOARCH == "wasm" { ++ t.Skip("causes call stack exhaustion on js/wasm") ++ } ++ for _, tt := range parseDepthTests { ++ if !tt.scope { ++ continue ++ } ++ for _, size := range []string{"small", "big"} { ++ t.Run(tt.name+"/"+size, func(t *testing.T) { ++ n := maxScopeDepth + 1 ++ if tt.scopeMultiplier > 0 { ++ n /= tt.scopeMultiplier ++ } ++ if size == "small" { ++ // Decrease the number of statements by 10, in order to check ++ // that we do not fail when under the limit. 10 is used to ++ // provide some wiggle room for cases where the surrounding ++ // scaffolding syntax adds some noise to the depth that changes ++ // on a per testcase basis. ++ n -= 10 ++ } ++ ++ pre, mid, post := split(tt.format) ++ if strings.Contains(mid, "«") { ++ left, base, right := split(mid) ++ mid = strings.Repeat(left, n) + base + strings.Repeat(right, n) ++ } else { ++ mid = strings.Repeat(mid, n) ++ } ++ input := pre + mid + post ++ ++ fset := token.NewFileSet() ++ _, err := ParseFile(fset, "", input, DeclarationErrors) ++ if size == "small" { ++ if err != nil { ++ t.Errorf("ParseFile(...): %v (want success)", err) ++ } ++ } else { ++ expected := "exceeded max scope depth during object resolution" ++ if err == nil || !strings.HasSuffix(err.Error(), expected) { ++ t.Errorf("ParseFile(...) = _, %v, want %q", err, expected) ++ } ++ } ++ }) ++ } ++ } ++} +diff --git a/src/go/parser/resolver.go b/src/go/parser/resolver.go +index cf92c7e4f57..f55bdb7f177 100644 +--- a/src/go/parser/resolver.go ++++ b/src/go/parser/resolver.go +@@ -25,6 +25,7 @@ func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, str + declErr: declErr, + topScope: pkgScope, + pkgScope: pkgScope, ++ depth: 1, + } + + for _, decl := range file.Decls { +@@ -53,6 +54,8 @@ func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, str + file.Unresolved = r.unresolved[0:i] + } + ++const maxScopeDepth int = 1e3 ++ + type resolver struct { + handle *token.File + declErr func(token.Pos, string) +@@ -61,6 +64,7 @@ type resolver struct { + pkgScope *ast.Scope // pkgScope.Outer == nil + topScope *ast.Scope // top-most scope; may be pkgScope + unresolved []*ast.Ident // unresolved identifiers ++ depth int // scope depth + + // Label scopes + // (maintained by open/close LabelScope) +@@ -83,6 +87,10 @@ func (r *resolver) sprintf(format string, args ...interface{}) string { + } + + func (r *resolver) openScope(pos token.Pos) { ++ r.depth++ ++ if r.depth > maxScopeDepth { ++ panic(bailout{pos: pos, msg: "exceeded max scope depth during object resolution"}) ++ } + if debugResolve { + r.dump("opening scope @%v", pos) + } +@@ -90,6 +98,7 @@ func (r *resolver) openScope(pos token.Pos) { + } + + func (r *resolver) closeScope() { ++ r.depth-- + if debugResolve { + r.dump("closing scope") + } +-- +2.30.2 + diff --git a/0007-release-branch.go1.17-net-http-don-t-strip-whitespac.patch b/0007-release-branch.go1.17-net-http-don-t-strip-whitespac.patch new file mode 100644 index 0000000..7fdcd6f --- /dev/null +++ b/0007-release-branch.go1.17-net-http-don-t-strip-whitespac.patch @@ -0,0 +1,62 @@ +From 4ad62aecaf57ca3adc11a04bd2113bdbee6249c3 Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Wed, 1 Jun 2022 11:17:07 -0700 +Subject: [PATCH 03/11] [release-branch.go1.17] net/http: don't strip + whitespace from Transfer-Encoding headers + +Do not accept "Transfer-Encoding: \rchunked" as a valid TE header +setting chunked encoding. + +Thanks to Zeyu Zhang (https://www.zeyu2001.com/) for identifying +the issue. + +For #53188 +For CVE-2022-1705 +Fixes #53432 + +Change-Id: I1a16631425159267f2eca68056b057192a7edf6c +Reviewed-on: https://go-review.googlesource.com/c/go/+/409874 +Reviewed-by: Roland Shoemaker +Reviewed-by: Brad Fitzpatrick +(cherry picked from commit e5017a93fcde94f09836200bca55324af037ee5f) +Reviewed-on: https://go-review.googlesource.com/c/go/+/415217 +Reviewed-by: Dmitri Shuralyov +Run-TryBot: Dmitri Shuralyov +Reviewed-by: Dmitri Shuralyov +TryBot-Result: Gopher Robot + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/415217 +--- + src/net/http/serve_test.go | 1 + + src/net/http/transfer.go | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go +index 6394da3bb7c..bfac783e3a9 100644 +--- a/src/net/http/serve_test.go ++++ b/src/net/http/serve_test.go +@@ -6189,6 +6189,7 @@ func TestUnsupportedTransferEncodingsReturn501(t *testing.T) { + "fugazi", + "foo-bar", + "unknown", ++ "\rchunked", + } + + for _, badTE := range unsupportedTEs { +diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go +index 85c2e5a360d..3894007d306 100644 +--- a/src/net/http/transfer.go ++++ b/src/net/http/transfer.go +@@ -639,7 +639,7 @@ func (t *transferReader) parseTransferEncoding() error { + if len(raw) != 1 { + return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", raw)} + } +- if !ascii.EqualFold(textproto.TrimString(raw[0]), "chunked") { ++ if !ascii.EqualFold(raw[0], "chunked") { + return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", raw[0])} + } + +-- +2.30.2 + diff --git a/0008-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch b/0008-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch new file mode 100644 index 0000000..077af15 --- /dev/null +++ b/0008-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch @@ -0,0 +1,168 @@ +From 106c859f68c3137cfa05c433a9b90494db386fda Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Tue, 29 Mar 2022 15:52:09 -0700 +Subject: [PATCH 04/11] [release-branch.go1.17] encoding/xml: limit depth of + nesting in unmarshal + +Prevent exhausting the stack limit when unmarshalling extremely deeply +nested structures into nested types. + +Fixes #53715 +Updates #53611 +Fixes CVE-2022-30633 + +Change-Id: Ic6c5d41674c93cfc9a316135a408db9156d39c59 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1421319 +Reviewed-by: Damien Neil +Reviewed-by: Julie Qiu +(cherry picked from commit ebee00a55e28931b2cad0e76207a73712b000432) +Reviewed-on: https://go-review.googlesource.com/c/go/+/417069 +Reviewed-by: Heschi Kreinick +Run-TryBot: Michael Knyszek +TryBot-Result: Gopher Robot + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/417069 +--- + src/encoding/xml/read.go | 27 +++++++++++++++++++-------- + src/encoding/xml/read_test.go | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+), 8 deletions(-) + +diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go +index ef5df3f7f6a..e0ed8b527ce 100644 +--- a/src/encoding/xml/read.go ++++ b/src/encoding/xml/read.go +@@ -148,7 +148,7 @@ func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error { + if val.Kind() != reflect.Ptr { + return errors.New("non-pointer passed to Unmarshal") + } +- return d.unmarshal(val.Elem(), start) ++ return d.unmarshal(val.Elem(), start, 0) + } + + // An UnmarshalError represents an error in the unmarshaling process. +@@ -304,8 +304,15 @@ var ( + textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + ) + ++const maxUnmarshalDepth = 10000 ++ ++var errExeceededMaxUnmarshalDepth = errors.New("exceeded max depth") ++ + // Unmarshal a single XML element into val. +-func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error { ++func (d *Decoder) unmarshal(val reflect.Value, start *StartElement, depth int) error { ++ if depth >= maxUnmarshalDepth { ++ return errExeceededMaxUnmarshalDepth ++ } + // Find start element if we need it. + if start == nil { + for { +@@ -398,7 +405,7 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error { + v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem()))) + + // Recur to read element into slice. +- if err := d.unmarshal(v.Index(n), start); err != nil { ++ if err := d.unmarshal(v.Index(n), start, depth+1); err != nil { + v.SetLen(n) + return err + } +@@ -521,13 +528,15 @@ Loop: + case StartElement: + consumed := false + if sv.IsValid() { +- consumed, err = d.unmarshalPath(tinfo, sv, nil, &t) ++ // unmarshalPath can call unmarshal, so we need to pass the depth through so that ++ // we can continue to enforce the maximum recusion limit. ++ consumed, err = d.unmarshalPath(tinfo, sv, nil, &t, depth) + if err != nil { + return err + } + if !consumed && saveAny.IsValid() { + consumed = true +- if err := d.unmarshal(saveAny, &t); err != nil { ++ if err := d.unmarshal(saveAny, &t, depth+1); err != nil { + return err + } + } +@@ -672,7 +681,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) { + // The consumed result tells whether XML elements have been consumed + // from the Decoder until start's matching end element, or if it's + // still untouched because start is uninteresting for sv's fields. +-func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) { ++func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement, depth int) (consumed bool, err error) { + recurse := false + Loop: + for i := range tinfo.fields { +@@ -687,7 +696,7 @@ Loop: + } + if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local { + // It's a perfect match, unmarshal the field. +- return true, d.unmarshal(finfo.value(sv, initNilPointers), start) ++ return true, d.unmarshal(finfo.value(sv, initNilPointers), start, depth+1) + } + if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local { + // It's a prefix for the field. Break and recurse +@@ -716,7 +725,9 @@ Loop: + } + switch t := tok.(type) { + case StartElement: +- consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t) ++ // the recursion depth of unmarshalPath is limited to the path length specified ++ // by the struct field tag, so we don't increment the depth here. ++ consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t, depth) + if err != nil { + return true, err + } +diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go +index 8c2e70fa22e..8c940aefb81 100644 +--- a/src/encoding/xml/read_test.go ++++ b/src/encoding/xml/read_test.go +@@ -5,8 +5,11 @@ + package xml + + import ( ++ "bytes" ++ "errors" + "io" + "reflect" ++ "runtime" + "strings" + "testing" + "time" +@@ -1079,3 +1082,32 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) { + t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) + } + } ++ ++func TestCVE202230633(t *testing.T) { ++ if runtime.GOARCH == "wasm" { ++ t.Skip("causes memory exhaustion on js/wasm") ++ } ++ defer func() { ++ p := recover() ++ if p != nil { ++ t.Fatal("Unmarshal panicked") ++ } ++ }() ++ var example struct { ++ Things []string ++ } ++ Unmarshal(bytes.Repeat([]byte(""), 17_000_000), &example) ++} ++ ++func TestCVE202228131(t *testing.T) { ++ type nested struct { ++ Parent *nested `xml:",any"` ++ } ++ var n nested ++ err := Unmarshal(bytes.Repeat([]byte(""), maxUnmarshalDepth+1), &n) ++ if err == nil { ++ t.Fatal("Unmarshal did not fail") ++ } else if !errors.Is(err, errExeceededMaxUnmarshalDepth) { ++ t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth) ++ } ++} +-- +2.30.2 + diff --git a/0009-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch b/0009-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch new file mode 100644 index 0000000..13f56a5 --- /dev/null +++ b/0009-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch @@ -0,0 +1,138 @@ +From 8747af9a1098e8fa497441be4c4a79a23de31a98 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Tue, 7 Jun 2022 13:00:43 -0700 +Subject: [PATCH 05/11] [release-branch.go1.17] encoding/gob: add a depth limit + for ignored fields + +Enforce a nesting limit of 10,000 for ignored fields during decoding +of messages. This prevents the possibility of triggering stack +exhaustion. + +Fixes #53709 +Updates #53615 +Fixes CVE-2022-30635 + +Change-Id: I05103d06dd5ca3945fcba3c1f5d3b5a645e8fb0f +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1484771 +Reviewed-by: Damien Neil +Reviewed-by: Tatiana Bradley +(cherry picked from commit 55e8f938d22bfec29cc9dc9671044c5a41d1ea9c) +Reviewed-on: https://go-review.googlesource.com/c/go/+/417074 +Run-TryBot: Heschi Kreinick +TryBot-Result: Gopher Robot +Reviewed-by: Heschi Kreinick + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/417074 +--- + src/encoding/gob/decode.go | 19 ++++++++++++------- + src/encoding/gob/gobencdec_test.go | 24 ++++++++++++++++++++++++ + 2 files changed, 36 insertions(+), 7 deletions(-) + +diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go +index d2f6c749b1b..0e0ec75cccc 100644 +--- a/src/encoding/gob/decode.go ++++ b/src/encoding/gob/decode.go +@@ -871,8 +871,13 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg + return &op + } + ++var maxIgnoreNestingDepth = 10000 ++ + // decIgnoreOpFor returns the decoding op for a field that has no destination. +-func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp { ++func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp { ++ if depth > maxIgnoreNestingDepth { ++ error_(errors.New("invalid nesting depth")) ++ } + // If this type is already in progress, it's a recursive type (e.g. map[string]*T). + // Return the pointer to the op we're already building. + if opPtr := inProgress[wireId]; opPtr != nil { +@@ -896,7 +901,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) + errorf("bad data: undefined type %s", wireId.string()) + case wire.ArrayT != nil: + elemId := wire.ArrayT.Elem +- elemOp := dec.decIgnoreOpFor(elemId, inProgress) ++ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) + op = func(i *decInstr, state *decoderState, value reflect.Value) { + state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len) + } +@@ -904,15 +909,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) + case wire.MapT != nil: + keyId := dec.wireType[wireId].MapT.Key + elemId := dec.wireType[wireId].MapT.Elem +- keyOp := dec.decIgnoreOpFor(keyId, inProgress) +- elemOp := dec.decIgnoreOpFor(elemId, inProgress) ++ keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1) ++ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) + op = func(i *decInstr, state *decoderState, value reflect.Value) { + state.dec.ignoreMap(state, *keyOp, *elemOp) + } + + case wire.SliceT != nil: + elemId := wire.SliceT.Elem +- elemOp := dec.decIgnoreOpFor(elemId, inProgress) ++ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1) + op = func(i *decInstr, state *decoderState, value reflect.Value) { + state.dec.ignoreSlice(state, *elemOp) + } +@@ -1073,7 +1078,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de + func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine { + engine := new(decEngine) + engine.instr = make([]decInstr, 1) // one item +- op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp)) ++ op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0) + ovfl := overflow(dec.typeString(remoteId)) + engine.instr[0] = decInstr{*op, 0, nil, ovfl} + engine.numInstr = 1 +@@ -1118,7 +1123,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn + localField, present := srt.FieldByName(wireField.Name) + // TODO(r): anonymous names + if !present || !isExported(wireField.Name) { +- op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp)) ++ op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0) + engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl} + continue + } +diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go +index 6d2c8db42d0..1b52ecc6c84 100644 +--- a/src/encoding/gob/gobencdec_test.go ++++ b/src/encoding/gob/gobencdec_test.go +@@ -12,6 +12,7 @@ import ( + "fmt" + "io" + "net" ++ "reflect" + "strings" + "testing" + "time" +@@ -796,3 +797,26 @@ func TestNetIP(t *testing.T) { + t.Errorf("decoded to %v, want 1.2.3.4", ip.String()) + } + } ++ ++func TestIngoreDepthLimit(t *testing.T) { ++ // We don't test the actual depth limit because it requires building an ++ // extremely large message, which takes quite a while. ++ oldNestingDepth := maxIgnoreNestingDepth ++ maxIgnoreNestingDepth = 100 ++ defer func() { maxIgnoreNestingDepth = oldNestingDepth }() ++ b := new(bytes.Buffer) ++ enc := NewEncoder(b) ++ typ := reflect.TypeOf(int(0)) ++ nested := reflect.ArrayOf(1, typ) ++ for i := 0; i < 100; i++ { ++ nested = reflect.ArrayOf(1, nested) ++ } ++ badStruct := reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})) ++ enc.Encode(badStruct.Interface()) ++ dec := NewDecoder(b) ++ var output struct{ Hello int } ++ expectedErr := "invalid nesting depth" ++ if err := dec.Decode(&output); err == nil || err.Error() != expectedErr { ++ t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err) ++ } ++} +-- +2.30.2 + diff --git a/0010-release-branch.go1.17-io-fs-fix-stack-exhaustion-in-.patch b/0010-release-branch.go1.17-io-fs-fix-stack-exhaustion-in-.patch new file mode 100644 index 0000000..c194378 --- /dev/null +++ b/0010-release-branch.go1.17-io-fs-fix-stack-exhaustion-in-.patch @@ -0,0 +1,96 @@ +From a8d44d0477f2182563e279da115cbc164d639f33 Mon Sep 17 00:00:00 2001 +From: Julie Qiu +Date: Thu, 23 Jun 2022 23:17:53 +0000 +Subject: [PATCH 06/11] [release-branch.go1.17] io/fs: fix stack exhaustion in + Glob + +A limit is added to the number of path separators allowed by an input to +Glob, to prevent stack exhaustion issues. + +Thanks to Juho Nurminen of Mattermost who reported a similar issue in +path/filepath. + +Fixes #53719 +Updates #53415 +Fixes CVE-2022-30630 + +Change-Id: I5a9d02591fed90cd3d52627f5945f1301e53465d +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1497588 +Reviewed-by: Roland Shoemaker +(cherry picked from commit fdccc5d7bd0f276d0a8de3a818ca844f0bed5d97) +Reviewed-on: https://go-review.googlesource.com/c/go/+/417072 +Reviewed-by: Heschi Kreinick +TryBot-Result: Gopher Robot +Run-TryBot: Michael Knyszek + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/417072 +--- + src/io/fs/glob.go | 14 ++++++++++++-- + src/io/fs/glob_test.go | 10 ++++++++++ + 2 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/src/io/fs/glob.go b/src/io/fs/glob.go +index 45d9cb61b96..0e529cd05d1 100644 +--- a/src/io/fs/glob.go ++++ b/src/io/fs/glob.go +@@ -31,6 +31,16 @@ type GlobFS interface { + // Otherwise, Glob uses ReadDir to traverse the directory tree + // and look for matches for the pattern. + func Glob(fsys FS, pattern string) (matches []string, err error) { ++ return globWithLimit(fsys, pattern, 0) ++} ++ ++func globWithLimit(fsys FS, pattern string, depth int) (matches []string, err error) { ++ // This limit is added to prevent stack exhaustion issues. See ++ // CVE-2022-30630. ++ const pathSeparatorsLimit = 10000 ++ if depth > pathSeparatorsLimit { ++ return nil, path.ErrBadPattern ++ } + if fsys, ok := fsys.(GlobFS); ok { + return fsys.Glob(pattern) + } +@@ -59,9 +69,9 @@ func Glob(fsys FS, pattern string) (matches []string, err error) { + } + + var m []string +- m, err = Glob(fsys, dir) ++ m, err = globWithLimit(fsys, dir, depth+1) + if err != nil { +- return ++ return nil, err + } + for _, d := range m { + matches, err = glob(fsys, d, file, matches) +diff --git a/src/io/fs/glob_test.go b/src/io/fs/glob_test.go +index f19bebed77f..d052eab3713 100644 +--- a/src/io/fs/glob_test.go ++++ b/src/io/fs/glob_test.go +@@ -8,6 +8,7 @@ import ( + . "io/fs" + "os" + "path" ++ "strings" + "testing" + ) + +@@ -55,6 +56,15 @@ func TestGlobError(t *testing.T) { + } + } + ++func TestCVE202230630(t *testing.T) { ++ // Prior to CVE-2022-30630, a stack exhaustion would occur given a large ++ // number of separators. There is now a limit of 10,000. ++ _, err := Glob(os.DirFS("."), "/*"+strings.Repeat("/", 10001)) ++ if err != path.ErrBadPattern { ++ t.Fatalf("Glob returned err=%v, want %v", err, path.ErrBadPattern) ++ } ++} ++ + // contains reports whether vector contains the string s. + func contains(vector []string, s string) bool { + for _, elem := range vector { +-- +2.30.2 + diff --git a/0011-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch b/0011-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch new file mode 100644 index 0000000..661634a --- /dev/null +++ b/0011-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch @@ -0,0 +1,85 @@ +From 7b98bf3a8711126c532033ca89647f3b743b58ec Mon Sep 17 00:00:00 2001 +From: Julie Qiu +Date: Thu, 23 Jun 2022 23:18:56 +0000 +Subject: [PATCH 07/11] [release-branch.go1.17] path/filepath: fix stack + exhaustion in Glob + +A limit is added to the number of path separators allowed by an input to +Glob, to prevent stack exhaustion issues. + +Thanks to Juho Nurminen of Mattermost who reported the issue. + +Fixes #53713 +Updates #53416 +Fixes CVE-2022-30632 + +Change-Id: I1b9fd4faa85411a05dbc91dceae1c0c8eb021f07 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1498176 +Reviewed-by: Roland Shoemaker +(cherry picked from commit d182a6d1217fd0d04c9babfa9a7ccd3515435c39) +Reviewed-on: https://go-review.googlesource.com/c/go/+/417073 +Reviewed-by: Heschi Kreinick +TryBot-Result: Gopher Robot +Run-TryBot: Michael Knyszek + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/417073 +--- + src/path/filepath/match.go | 12 +++++++++++- + src/path/filepath/match_test.go | 10 ++++++++++ + 2 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/src/path/filepath/match.go b/src/path/filepath/match.go +index c77a26952a6..55ed1d75ae1 100644 +--- a/src/path/filepath/match.go ++++ b/src/path/filepath/match.go +@@ -241,6 +241,16 @@ func getEsc(chunk string) (r rune, nchunk string, err error) { + // The only possible returned error is ErrBadPattern, when pattern + // is malformed. + func Glob(pattern string) (matches []string, err error) { ++ return globWithLimit(pattern, 0) ++} ++ ++func globWithLimit(pattern string, depth int) (matches []string, err error) { ++ // This limit is used prevent stack exhaustion issues. See CVE-2022-30632. ++ const pathSeparatorsLimit = 10000 ++ if depth == pathSeparatorsLimit { ++ return nil, ErrBadPattern ++ } ++ + // Check pattern is well-formed. + if _, err := Match(pattern, ""); err != nil { + return nil, err +@@ -270,7 +280,7 @@ func Glob(pattern string) (matches []string, err error) { + } + + var m []string +- m, err = Glob(dir) ++ m, err = globWithLimit(dir, depth+1) + if err != nil { + return + } +diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go +index 375c41a7e9d..d6282596fed 100644 +--- a/src/path/filepath/match_test.go ++++ b/src/path/filepath/match_test.go +@@ -155,6 +155,16 @@ func TestGlob(t *testing.T) { + } + } + ++func TestCVE202230632(t *testing.T) { ++ // Prior to CVE-2022-30632, this would cause a stack exhaustion given a ++ // large number of separators (more than 4,000,000). There is now a limit ++ // of 10,000. ++ _, err := Glob("/*" + strings.Repeat("/", 10001)) ++ if err != ErrBadPattern { ++ t.Fatalf("Glob returned err=%v, want ErrBadPattern", err) ++ } ++} ++ + func TestGlobError(t *testing.T) { + bad := []string{`[]`, `nonexist/[]`} + for _, pattern := range bad { +-- +2.30.2 + diff --git a/0012-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch b/0012-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch new file mode 100644 index 0000000..9be1eea --- /dev/null +++ b/0012-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch @@ -0,0 +1,69 @@ +From cedbe8f7a1f0d174636e70de68d85499d8025000 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Mon, 28 Mar 2022 18:41:26 -0700 +Subject: [PATCH 08/11] [release-branch.go1.17] encoding/xml: use iterative + Skip, rather than recursive + +Prevents exhausting the stack limit in _incredibly_ deeply nested +structures. + +Fixes #53711 +Updates #53614 +Fixes CVE-2022-28131 + +Change-Id: I47db4595ce10cecc29fbd06afce7b299868599e6 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1419912 +Reviewed-by: Julie Qiu +Reviewed-by: Damien Neil +(cherry picked from commit 9278cb78443d2b4deb24cbb5b61c9ba5ac688d49) +Reviewed-on: https://go-review.googlesource.com/c/go/+/417068 +TryBot-Result: Gopher Robot +Reviewed-by: Heschi Kreinick +Run-TryBot: Michael Knyszek + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/417068 +--- + src/encoding/xml/read.go | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go +index e0ed8b527ce..c77579880cb 100644 +--- a/src/encoding/xml/read.go ++++ b/src/encoding/xml/read.go +@@ -743,12 +743,12 @@ Loop: + } + + // Skip reads tokens until it has consumed the end element +-// matching the most recent start element already consumed. +-// It recurs if it encounters a start element, so it can be used to +-// skip nested structures. ++// matching the most recent start element already consumed, ++// skipping nested structures. + // It returns nil if it finds an end element matching the start + // element; otherwise it returns an error describing the problem. + func (d *Decoder) Skip() error { ++ var depth int64 + for { + tok, err := d.Token() + if err != nil { +@@ -756,11 +756,12 @@ func (d *Decoder) Skip() error { + } + switch tok.(type) { + case StartElement: +- if err := d.Skip(); err != nil { +- return err +- } ++ depth++ + case EndElement: +- return nil ++ if depth == 0 { ++ return nil ++ } ++ depth-- + } + } + } +-- +2.30.2 + diff --git a/0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch b/0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch new file mode 100644 index 0000000..7a54a71 --- /dev/null +++ b/0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch @@ -0,0 +1,133 @@ +From 8a445abc7f7e2ed41112f176a169b97859c8d425 Mon Sep 17 00:00:00 2001 +From: Tatiana Bradley +Date: Fri, 6 May 2022 11:25:06 -0400 +Subject: [PATCH 09/11] [release-branch.go1.17] compress/gzip: fix stack + exhaustion bug in Reader.Read + +Replace recursion with iteration in Reader.Read to avoid stack +exhaustion when there are a large number of files. + +Fixes CVE-2022-30631 +Fixes #53717 +Updates #53168 + +Change-Id: I47d8afe3f2d40b0213ab61431df9b221794dbfe0 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1455673 +Reviewed-by: Roland Shoemaker +Reviewed-by: Julie Qiu +(cherry picked from commit cf498969c8a0bae9d7a24b98fc1f66c824a4775d) +Reviewed-on: https://go-review.googlesource.com/c/go/+/417071 +Reviewed-by: Heschi Kreinick +Run-TryBot: Michael Knyszek +TryBot-Result: Gopher Robot + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/417071 +--- + src/compress/gzip/gunzip.go | 60 +++++++++++++++----------------- + src/compress/gzip/gunzip_test.go | 16 +++++++++ + 2 files changed, 45 insertions(+), 31 deletions(-) + +diff --git a/src/compress/gzip/gunzip.go b/src/compress/gzip/gunzip.go +index 924bce10b7c..237b2b928bf 100644 +--- a/src/compress/gzip/gunzip.go ++++ b/src/compress/gzip/gunzip.go +@@ -248,42 +248,40 @@ func (z *Reader) Read(p []byte) (n int, err error) { + return 0, z.err + } + +- n, z.err = z.decompressor.Read(p) +- z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n]) +- z.size += uint32(n) +- if z.err != io.EOF { +- // In the normal case we return here. +- return n, z.err +- } ++ for n == 0 { ++ n, z.err = z.decompressor.Read(p) ++ z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n]) ++ z.size += uint32(n) ++ if z.err != io.EOF { ++ // In the normal case we return here. ++ return n, z.err ++ } + +- // Finished file; check checksum and size. +- if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil { +- z.err = noEOF(err) +- return n, z.err +- } +- digest := le.Uint32(z.buf[:4]) +- size := le.Uint32(z.buf[4:8]) +- if digest != z.digest || size != z.size { +- z.err = ErrChecksum +- return n, z.err +- } +- z.digest, z.size = 0, 0 ++ // Finished file; check checksum and size. ++ if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil { ++ z.err = noEOF(err) ++ return n, z.err ++ } ++ digest := le.Uint32(z.buf[:4]) ++ size := le.Uint32(z.buf[4:8]) ++ if digest != z.digest || size != z.size { ++ z.err = ErrChecksum ++ return n, z.err ++ } ++ z.digest, z.size = 0, 0 + +- // File is ok; check if there is another. +- if !z.multistream { +- return n, io.EOF +- } +- z.err = nil // Remove io.EOF ++ // File is ok; check if there is another. ++ if !z.multistream { ++ return n, io.EOF ++ } ++ z.err = nil // Remove io.EOF + +- if _, z.err = z.readHeader(); z.err != nil { +- return n, z.err ++ if _, z.err = z.readHeader(); z.err != nil { ++ return n, z.err ++ } + } + +- // Read from next file, if necessary. +- if n > 0 { +- return n, nil +- } +- return z.Read(p) ++ return n, nil + } + + // Close closes the Reader. It does not close the underlying io.Reader. +diff --git a/src/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go +index 17c23e8a9be..6fe8ddcf558 100644 +--- a/src/compress/gzip/gunzip_test.go ++++ b/src/compress/gzip/gunzip_test.go +@@ -515,3 +515,19 @@ func TestTruncatedStreams(t *testing.T) { + } + } + } ++ ++func TestCVE202230631(t *testing.T) { ++ var empty = []byte{0x1f, 0x8b, 0x08, 0x00, 0xa7, 0x8f, 0x43, 0x62, 0x00, ++ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} ++ r := bytes.NewReader(bytes.Repeat(empty, 4e6)) ++ z, err := NewReader(r) ++ if err != nil { ++ t.Fatalf("NewReader: got %v, want nil", err) ++ } ++ // Prior to CVE-2022-30631 fix, this would cause an unrecoverable panic due ++ // to stack exhaustion. ++ _, err = z.Read(make([]byte, 10)) ++ if err != io.EOF { ++ t.Errorf("Reader.Read: got %v, want %v", err, io.EOF) ++ } ++} +-- +2.30.2 + diff --git a/0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch b/0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch new file mode 100644 index 0000000..f8f418a --- /dev/null +++ b/0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch @@ -0,0 +1,69 @@ +From b2815a72bef3f829c5ac7735feddb034f5501cc0 Mon Sep 17 00:00:00 2001 +From: Tatiana Bradley +Date: Thu, 12 May 2022 14:58:29 -0400 +Subject: [PATCH 10/11] [release-branch.go1.17] crypto/tls: randomly generate + ticket_age_add + +As required by RFC 8446, section 4.6.1, ticket_age_add now holds a +random 32-bit value. Before this change, this value was always set +to 0. + +This change also documents the reasoning for always setting +ticket_nonce to 0. The value ticket_nonce must be unique per +connection, but we only ever send one ticket per connection. + +Updates #52814 +Fixes #52832 +Fixes CVE-2022-30629 + +Change-Id: I6c2fc6ca0376b7b968abd59d6d3d3854c1ab68bb +Reviewed-on: https://go-review.googlesource.com/c/go/+/405994 +Reviewed-by: Tatiana Bradley +Reviewed-by: Roland Shoemaker +Run-TryBot: Tatiana Bradley +TryBot-Result: Gopher Robot +(cherry picked from commit fe4de36198794c447fbd9d7cc2d7199a506c76a5) +Reviewed-on: https://go-review.googlesource.com/c/go/+/408574 +Run-TryBot: Roland Shoemaker + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/408574 +--- + src/crypto/tls/handshake_server_tls13.go | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go +index 08251b84def..6aa52698a3a 100644 +--- a/src/crypto/tls/handshake_server_tls13.go ++++ b/src/crypto/tls/handshake_server_tls13.go +@@ -10,6 +10,7 @@ import ( + "crypto" + "crypto/hmac" + "crypto/rsa" ++ "encoding/binary" + "errors" + "hash" + "io" +@@ -741,6 +742,19 @@ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error { + } + m.lifetime = uint32(maxSessionTicketLifetime / time.Second) + ++ // ticket_age_add is a random 32-bit value. See RFC 8446, section 4.6.1 ++ // The value is not stored anywhere; we never need to check the ticket age ++ // because 0-RTT is not supported. ++ ageAdd := make([]byte, 4) ++ _, err = hs.c.config.rand().Read(ageAdd) ++ if err != nil { ++ return err ++ } ++ m.ageAdd = binary.LittleEndian.Uint32(ageAdd) ++ ++ // ticket_nonce, which must be unique per connection, is always left at ++ // zero because we only ever send one ticket per connection. ++ + if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil { + return err + } +-- +2.30.2 + diff --git a/0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch b/0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch new file mode 100644 index 0000000..0928140 --- /dev/null +++ b/0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch @@ -0,0 +1,246 @@ +From 07a30769186210c1b1e25943824743355c4e50f5 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Mon, 25 Apr 2022 19:02:35 -0700 +Subject: [PATCH 11/11] [release-branch.go1.17] crypto/rand: properly handle + large Read on windows + +Use the batched reader to chunk large Read calls on windows to a max of +1 << 31 - 1 bytes. This prevents an infinite loop when trying to read +more than 1 << 32 -1 bytes, due to how RtlGenRandom works. + +This change moves the batched function from rand_unix.go to rand.go, +since it is now needed for both windows and unix implementations. + +Updates #52561 +Fixes #52932 +Fixes CVE-2022-30634 + +Change-Id: Id98fc4b1427e5cb2132762a445b2aed646a37473 +Reviewed-on: https://go-review.googlesource.com/c/go/+/402257 +Run-TryBot: Roland Shoemaker +Reviewed-by: Filippo Valsorda +Reviewed-by: Filippo Valsorda +TryBot-Result: Gopher Robot +(cherry picked from commit bb1f4416180511231de6d17a1f2f55c82aafc863) +Reviewed-on: https://go-review.googlesource.com/c/go/+/406635 +Reviewed-by: Damien Neil + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/406635 +--- + src/crypto/rand/rand.go | 18 ++++++++++++++++++ + src/crypto/rand/rand_batched.go | 22 ++++++---------------- + src/crypto/rand/rand_batched_test.go | 21 +++++++++++---------- + src/crypto/rand/rand_getentropy.go | 6 +++--- + src/crypto/rand/rand_unix.go | 4 ++-- + src/crypto/rand/rand_windows.go | 18 ++++++------------ + 6 files changed, 46 insertions(+), 43 deletions(-) + +diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go +index fddd1147e6e..f2c276008d7 100644 +--- a/src/crypto/rand/rand.go ++++ b/src/crypto/rand/rand.go +@@ -23,3 +23,21 @@ var Reader io.Reader + func Read(b []byte) (n int, err error) { + return io.ReadFull(Reader, b) + } ++ ++// batched returns a function that calls f to populate a []byte by chunking it ++// into subslices of, at most, readMax bytes. ++func batched(f func([]byte) error, readMax int) func([]byte) error { ++ return func(out []byte) error { ++ for len(out) > 0 { ++ read := len(out) ++ if read > readMax { ++ read = readMax ++ } ++ if err := f(out[:read]); err != nil { ++ return err ++ } ++ out = out[read:] ++ } ++ return nil ++ } ++} +diff --git a/src/crypto/rand/rand_batched.go b/src/crypto/rand/rand_batched.go +index d7c5bf3562d..8df715fdd14 100644 +--- a/src/crypto/rand/rand_batched.go ++++ b/src/crypto/rand/rand_batched.go +@@ -8,6 +8,7 @@ + package rand + + import ( ++ "errors" + "internal/syscall/unix" + ) + +@@ -16,20 +17,6 @@ func init() { + altGetRandom = batched(getRandomBatch, maxGetRandomRead) + } + +-// batched returns a function that calls f to populate a []byte by chunking it +-// into subslices of, at most, readMax bytes. +-func batched(f func([]byte) bool, readMax int) func([]byte) bool { +- return func(buf []byte) bool { +- for len(buf) > readMax { +- if !f(buf[:readMax]) { +- return false +- } +- buf = buf[readMax:] +- } +- return len(buf) == 0 || f(buf) +- } +-} +- + // If the kernel is too old to support the getrandom syscall(), + // unix.GetRandom will immediately return ENOSYS and we will then fall back to + // reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS +@@ -37,7 +24,10 @@ func batched(f func([]byte) bool, readMax int) func([]byte) bool { + // If the kernel supports the getrandom() syscall, unix.GetRandom will block + // until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK). + // In this case, unix.GetRandom will not return an error. +-func getRandomBatch(p []byte) (ok bool) { ++func getRandomBatch(p []byte) error { + n, err := unix.GetRandom(p, 0) +- return n == len(p) && err == nil ++ if n != len(p) { ++ return errors.New("short read") ++ } ++ return err + } +diff --git a/src/crypto/rand/rand_batched_test.go b/src/crypto/rand/rand_batched_test.go +index 2d20922c825..b56345e50f1 100644 +--- a/src/crypto/rand/rand_batched_test.go ++++ b/src/crypto/rand/rand_batched_test.go +@@ -9,20 +9,21 @@ package rand + + import ( + "bytes" ++ "errors" + "testing" + ) + + func TestBatched(t *testing.T) { +- fillBatched := batched(func(p []byte) bool { ++ fillBatched := batched(func(p []byte) error { + for i := range p { + p[i] = byte(i) + } +- return true ++ return nil + }, 5) + + p := make([]byte, 13) +- if !fillBatched(p) { +- t.Fatal("batched function returned false") ++ if err := fillBatched(p); err != nil { ++ t.Fatalf("batched function returned error: %s", err) + } + expected := []byte{0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2} + if !bytes.Equal(expected, p) { +@@ -31,15 +32,15 @@ func TestBatched(t *testing.T) { + } + + func TestBatchedError(t *testing.T) { +- b := batched(func(p []byte) bool { return false }, 5) +- if b(make([]byte, 13)) { +- t.Fatal("batched function should have returned false") ++ b := batched(func(p []byte) error { return errors.New("") }, 5) ++ if b(make([]byte, 13)) == nil { ++ t.Fatal("batched function should have returned an error") + } + } + + func TestBatchedEmpty(t *testing.T) { +- b := batched(func(p []byte) bool { return false }, 5) +- if !b(make([]byte, 0)) { +- t.Fatal("empty slice should always return true") ++ b := batched(func(p []byte) error { return errors.New("") }, 5) ++ if err := b(make([]byte, 0)); err != nil { ++ t.Fatalf("empty slice should always return nil: %s", err) + } + } +diff --git a/src/crypto/rand/rand_getentropy.go b/src/crypto/rand/rand_getentropy.go +index dd725372ad9..b1c19f3d0da 100644 +--- a/src/crypto/rand/rand_getentropy.go ++++ b/src/crypto/rand/rand_getentropy.go +@@ -15,7 +15,7 @@ func init() { + altGetRandom = getEntropy + } + +-func getEntropy(p []byte) (ok bool) { ++func getEntropy(p []byte) error { + // getentropy(2) returns a maximum of 256 bytes per call + for i := 0; i < len(p); i += 256 { + end := i + 256 +@@ -24,8 +24,8 @@ func getEntropy(p []byte) (ok bool) { + } + err := unix.GetEntropy(p[i:end]) + if err != nil { +- return false ++ return err + } + } +- return true ++ return nil + } +diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go +index 81277eb6a5d..3d11159a340 100644 +--- a/src/crypto/rand/rand_unix.go ++++ b/src/crypto/rand/rand_unix.go +@@ -46,7 +46,7 @@ type devReader struct { + + // altGetRandom if non-nil specifies an OS-specific function to get + // urandom-style randomness. +-var altGetRandom func([]byte) (ok bool) ++var altGetRandom func([]byte) (err error) + + func warnBlocked() { + println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel") +@@ -59,7 +59,7 @@ func (r *devReader) Read(b []byte) (n int, err error) { + t := time.AfterFunc(60*time.Second, warnBlocked) + defer t.Stop() + } +- if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) { ++ if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) == nil { + return len(b), nil + } + r.mu.Lock() +diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go +index 7379f1489ad..6c0655c72b6 100644 +--- a/src/crypto/rand/rand_windows.go ++++ b/src/crypto/rand/rand_windows.go +@@ -9,7 +9,6 @@ package rand + + import ( + "internal/syscall/windows" +- "os" + ) + + func init() { Reader = &rngReader{} } +@@ -17,16 +16,11 @@ func init() { Reader = &rngReader{} } + type rngReader struct{} + + func (r *rngReader) Read(b []byte) (n int, err error) { +- // RtlGenRandom only accepts 2**32-1 bytes at a time, so truncate. +- inputLen := uint32(len(b)) +- +- if inputLen == 0 { +- return 0, nil +- } +- +- err = windows.RtlGenRandom(b) +- if err != nil { +- return 0, os.NewSyscallError("RtlGenRandom", err) ++ // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at ++ // most 1<<31-1 bytes at a time so that this works the same on 32-bit ++ // and 64-bit systems. ++ if err := batched(windows.RtlGenRandom, 1<<31-1)(b); err != nil { ++ return 0, err + } +- return int(inputLen), nil ++ return len(b), nil + } +-- +2.30.2 + diff --git a/golang.spec b/golang.spec index f28b764..173442a 100644 --- a/golang.spec +++ b/golang.spec @@ -66,7 +66,7 @@ Name: golang Version: 1.17.3 -Release: 4 +Release: 5 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -157,6 +157,17 @@ Patch6001: 0001-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch Patch6002: 0002-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch Patch6003: 0003-release-branch.go1.17-syscall-fix-ForkLock-spurious-.patch Patch6004: 0004-backport-cmd-link-mark-unexported-methods-for-plugins.patch +Patch6005: 0005-release-branch.go1.17-net-http-preserve-nil-values-i.patch +Patch6006: 0006-release-branch.go1.17-go-parser-limit-recursion-dept.patch +Patch6007: 0007-release-branch.go1.17-net-http-don-t-strip-whitespac.patch +Patch6008: 0008-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch +Patch6009: 0009-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch +Patch6010: 0010-release-branch.go1.17-io-fs-fix-stack-exhaustion-in-.patch +Patch6011: 0011-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch +Patch6012: 0012-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch +Patch6013: 0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch +Patch6014: 0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch +Patch6015: 0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch ExclusiveArch: %{golang_arches} @@ -391,6 +402,14 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Tue Jul 26 2022 hanchao - 1.17.3-5 +- Type:CVE +- CVE:NA +- SUG:NA +- DESC: fix CVE-2022-32148,CVE-2022-1962,CVE-2022-1705,CVE-2022-30633, + CVE-2022-30635,CVE-2022-30630,CVE-2022-30632,CVE-2022-28131, + CVE-2022-30631,CVE-2022-30629,CVE-2022-30634 + * Tue Jun 28 2022 Bin Hu - 1.17.3-4 - Type:bugfix - CVE:NA -- Gitee From 1aa388fd4c12654a8d74f6e28ddd8afdaab79686 Mon Sep 17 00:00:00 2001 From: hanchao Date: Mon, 8 Aug 2022 17:26:39 +0800 Subject: [PATCH 6/7] golang: fix CVE-2022-32189 Score: 6.5 Reference: https://go-review.googlesource.com/c/go/+/419814 Conflict: NA Reason: fix CVE-2022-32189 (cherry picked from commit 6dd57444d5c99f2d24ba90f5b581eb41d3c7407a) --- ...o1.17-math-big-check-buffer-lengths-.patch | 125 ++++++++++++++++++ golang.spec | 9 +- 2 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 0016-release-branch.go1.17-math-big-check-buffer-lengths-.patch diff --git a/0016-release-branch.go1.17-math-big-check-buffer-lengths-.patch b/0016-release-branch.go1.17-math-big-check-buffer-lengths-.patch new file mode 100644 index 0000000..78f8090 --- /dev/null +++ b/0016-release-branch.go1.17-math-big-check-buffer-lengths-.patch @@ -0,0 +1,125 @@ +From dc903a8196a831d23e9b6504239e09a9e6bcd98a Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker +Date: Fri, 15 Jul 2022 10:43:44 -0700 +Subject: [PATCH] [release-branch.go1.17] math/big: check buffer lengths in + GobDecode + +In Float.GobDecode and Rat.GobDecode, check buffer sizes before +indexing slices. + +Updates #53871 +Fixes #54094 + +Change-Id: I1b652c32c2bc7a0e8aa7620f7be9b2740c568b0a +Reviewed-on: https://go-review.googlesource.com/c/go/+/417774 +TryBot-Result: Gopher Robot +Reviewed-by: Tatiana Bradley +Run-TryBot: Roland Shoemaker +(cherry picked from commit 055113ef364337607e3e72ed7d48df67fde6fc66) +Reviewed-on: https://go-review.googlesource.com/c/go/+/419814 +Reviewed-by: Julie Qiu +--- + src/math/big/floatmarsh.go | 7 +++++++ + src/math/big/floatmarsh_test.go | 12 ++++++++++++ + src/math/big/ratmarsh.go | 6 ++++++ + src/math/big/ratmarsh_test.go | 12 ++++++++++++ + 4 files changed, 37 insertions(+) + +diff --git a/src/math/big/floatmarsh.go b/src/math/big/floatmarsh.go +index d1c1dab069..990e085abe 100644 +--- a/src/math/big/floatmarsh.go ++++ b/src/math/big/floatmarsh.go +@@ -8,6 +8,7 @@ package big + + import ( + "encoding/binary" ++ "errors" + "fmt" + ) + +@@ -67,6 +68,9 @@ func (z *Float) GobDecode(buf []byte) error { + *z = Float{} + return nil + } ++ if len(buf) < 6 { ++ return errors.New("Float.GobDecode: buffer too small") ++ } + + if buf[0] != floatGobVersion { + return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0]) +@@ -83,6 +87,9 @@ func (z *Float) GobDecode(buf []byte) error { + z.prec = binary.BigEndian.Uint32(buf[2:]) + + if z.form == finite { ++ if len(buf) < 10 { ++ return errors.New("Float.GobDecode: buffer too small for finite form float") ++ } + z.exp = int32(binary.BigEndian.Uint32(buf[6:])) + z.mant = z.mant.setBytes(buf[10:]) + } +diff --git a/src/math/big/floatmarsh_test.go b/src/math/big/floatmarsh_test.go +index c056d78b80..401f45a51f 100644 +--- a/src/math/big/floatmarsh_test.go ++++ b/src/math/big/floatmarsh_test.go +@@ -137,3 +137,15 @@ func TestFloatJSONEncoding(t *testing.T) { + } + } + } ++ ++func TestFloatGobDecodeShortBuffer(t *testing.T) { ++ for _, tc := range [][]byte{ ++ []byte{0x1, 0x0, 0x0, 0x0}, ++ []byte{0x1, 0xfa, 0x0, 0x0, 0x0, 0x0}, ++ } { ++ err := NewFloat(0).GobDecode(tc) ++ if err == nil { ++ t.Error("expected GobDecode to return error for malformed input") ++ } ++ } ++} +diff --git a/src/math/big/ratmarsh.go b/src/math/big/ratmarsh.go +index fbc7b6002d..56102e845b 100644 +--- a/src/math/big/ratmarsh.go ++++ b/src/math/big/ratmarsh.go +@@ -45,12 +45,18 @@ func (z *Rat) GobDecode(buf []byte) error { + *z = Rat{} + return nil + } ++ if len(buf) < 5 { ++ return errors.New("Rat.GobDecode: buffer too small") ++ } + b := buf[0] + if b>>1 != ratGobVersion { + return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1) + } + const j = 1 + 4 + i := j + binary.BigEndian.Uint32(buf[j-4:j]) ++ if len(buf) < int(i) { ++ return errors.New("Rat.GobDecode: buffer too small") ++ } + z.a.neg = b&1 != 0 + z.a.abs = z.a.abs.setBytes(buf[j:i]) + z.b.abs = z.b.abs.setBytes(buf[i:]) +diff --git a/src/math/big/ratmarsh_test.go b/src/math/big/ratmarsh_test.go +index 351d109f8d..55a9878bb8 100644 +--- a/src/math/big/ratmarsh_test.go ++++ b/src/math/big/ratmarsh_test.go +@@ -123,3 +123,15 @@ func TestRatXMLEncoding(t *testing.T) { + } + } + } ++ ++func TestRatGobDecodeShortBuffer(t *testing.T) { ++ for _, tc := range [][]byte{ ++ []byte{0x2}, ++ []byte{0x2, 0x0, 0x0, 0x0, 0xff}, ++ } { ++ err := NewRat(1, 2).GobDecode(tc) ++ if err == nil { ++ t.Error("expected GobDecode to return error for malformed input") ++ } ++ } ++} +-- +2.30.2 + diff --git a/golang.spec b/golang.spec index 173442a..943a4ff 100644 --- a/golang.spec +++ b/golang.spec @@ -66,7 +66,7 @@ Name: golang Version: 1.17.3 -Release: 5 +Release: 6 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -168,6 +168,7 @@ Patch6012: 0012-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch Patch6013: 0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch Patch6014: 0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch Patch6015: 0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch +Patch6016: 0016-release-branch.go1.17-math-big-check-buffer-lengths-.patch ExclusiveArch: %{golang_arches} @@ -402,6 +403,12 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Mon Aug 8 2022 hanchao - 1.17.3-6 +- Type:CVE +- CVE:NA +- SUG:NA +- DESC: fix CVE-2022-32189 + * Tue Jul 26 2022 hanchao - 1.17.3-5 - Type:CVE - CVE:NA -- Gitee From b6345e0a6e6a49b8308745c8fec0acf737c0c8dc Mon Sep 17 00:00:00 2001 From: hanchao Date: Thu, 18 Aug 2022 17:48:04 +0800 Subject: [PATCH 7/7] golang: fix CVE-2022-29804,CVE-2022-29526 Score: CVE-2022-29804: 7.5, CVE-2022-29526: 5.3 Reference: https://go-review.googlesource.com/c/go/+/401595/, https://go-review.googlesource.com/c/go/+/401078/ Conflict: NA Reason: fix CVE-2022-29804,CVE-2022-29526 (cherry picked from commit 282de33531134134e5d590913baa6c92a2ddfd7c) --- ...-not-remove-prefix-.-when-following-.patch | 103 ++++++++++++++++++ ...o1.17-syscall-check-correct-group-in.patch | 53 +++++++++ golang.spec | 10 +- 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 0017-path-filepath-do-not-remove-prefix-.-when-following-.patch create mode 100644 0018-release-branch.go1.17-syscall-check-correct-group-in.patch diff --git a/0017-path-filepath-do-not-remove-prefix-.-when-following-.patch b/0017-path-filepath-do-not-remove-prefix-.-when-following-.patch new file mode 100644 index 0000000..0f44f38 --- /dev/null +++ b/0017-path-filepath-do-not-remove-prefix-.-when-following-.patch @@ -0,0 +1,103 @@ +From e903e474f9632a151fff2df3dd3e891395f1a8f1 Mon Sep 17 00:00:00 2001 +From: Yasuhiro Matsumoto +Date: Fri, 22 Apr 2022 10:07:51 +0900 +Subject: [PATCH 1/2] path/filepath: do not remove prefix "." when following + path contains ":". + +Fixes #52476 + +Change-Id: I9eb72ac7dbccd6322d060291f31831dc389eb9bb +Reviewed-on: https://go-review.googlesource.com/c/go/+/401595 +Auto-Submit: Ian Lance Taylor +Reviewed-by: Alex Brainman +Run-TryBot: Ian Lance Taylor +Reviewed-by: Ian Lance Taylor +Reviewed-by: Damien Neil +TryBot-Result: Gopher Robot + +Reference:https://go-review.googlesource.com/c/go/+/401595/ +Conflict:NA +--- + src/path/filepath/path.go | 14 +++++++++++++- + src/path/filepath/path_test.go | 3 +++ + src/path/filepath/path_windows_test.go | 26 ++++++++++++++++++++++++++ + 3 files changed, 42 insertions(+), 1 deletion(-) + +diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go +index b56534dead..8300a32cb1 100644 +--- a/src/path/filepath/path.go ++++ b/src/path/filepath/path.go +@@ -117,9 +117,21 @@ func Clean(path string) string { + case os.IsPathSeparator(path[r]): + // empty path element + r++ +- case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])): ++ case path[r] == '.' && r+1 == n: + // . element + r++ ++ case path[r] == '.' && os.IsPathSeparator(path[r+1]): ++ // ./ element ++ r++ ++ ++ for r < len(path) && os.IsPathSeparator(path[r]) { ++ r++ ++ } ++ if out.w == 0 && volumeNameLen(path[r:]) > 0 { ++ // When joining prefix "." and an absolute path on Windows, ++ // the prefix should not be removed. ++ out.append('.') ++ } + case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])): + // .. element: remove to last separator + r += 2 +diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go +index bc5509b49c..ed17a8854d 100644 +--- a/src/path/filepath/path_test.go ++++ b/src/path/filepath/path_test.go +@@ -93,6 +93,9 @@ var wincleantests = []PathTest{ + {`//host/share/foo/../baz`, `\\host\share\baz`}, + {`\\a\b\..\c`, `\\a\b\c`}, + {`\\a\b`, `\\a\b`}, ++ {`.\c:`, `.\c:`}, ++ {`.\c:\foo`, `.\c:\foo`}, ++ {`.\c:foo`, `.\c:foo`}, + } + + func TestClean(t *testing.T) { +diff --git a/src/path/filepath/path_windows_test.go b/src/path/filepath/path_windows_test.go +index 76a459ac96..3edafb5a85 100644 +--- a/src/path/filepath/path_windows_test.go ++++ b/src/path/filepath/path_windows_test.go +@@ -530,3 +530,29 @@ func TestNTNamespaceSymlink(t *testing.T) { + t.Errorf(`EvalSymlinks(%q): got %q, want %q`, filelink, got, want) + } + } ++ ++func TestIssue52476(t *testing.T) { ++ tests := []struct { ++ lhs, rhs string ++ want string ++ }{ ++ {`..\.`, `C:`, `..\C:`}, ++ {`..`, `C:`, `..\C:`}, ++ {`.`, `:`, `:`}, ++ {`.`, `C:`, `.\C:`}, ++ {`.`, `C:/a/b/../c`, `.\C:\a\c`}, ++ {`.`, `\C:`, `.\C:`}, ++ {`C:\`, `.`, `C:\`}, ++ {`C:\`, `C:\`, `C:\C:`}, ++ {`C`, `:`, `C\:`}, ++ {`\.`, `C:`, `\C:`}, ++ {`\`, `C:`, `\C:`}, ++ } ++ ++ for _, test := range tests { ++ got := filepath.Join(test.lhs, test.rhs) ++ if got != test.want { ++ t.Errorf(`Join(%q, %q): got %q, want %q`, test.lhs, test.rhs, got, test.want) ++ } ++ } ++} +-- +2.30.2 + diff --git a/0018-release-branch.go1.17-syscall-check-correct-group-in.patch b/0018-release-branch.go1.17-syscall-check-correct-group-in.patch new file mode 100644 index 0000000..2387211 --- /dev/null +++ b/0018-release-branch.go1.17-syscall-check-correct-group-in.patch @@ -0,0 +1,53 @@ +From 66cff0cda766c1533373fabf3bc26fc3397e55d5 Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Tue, 12 Apr 2022 13:38:17 -0700 +Subject: [PATCH 2/2] [release-branch.go1.17] syscall: check correct group in + Faccessat + +The Faccessat call checks the user, group, or other permission bits of a +file to see if the calling process can access it. The test to see if the +group permissions should be used was made with the wrong group id, using +the process's group id rather than the file's group id. Fix this to use +the correct group id. + +No test since we cannot easily change file permissions when not running +as root and the test is meaningless if running as root. + +For #52313 +Fixes #52439 + +Change-Id: I4e2c84754b0af7830b40fd15dedcbc58374d75ee +Reviewed-on: https://go-review.googlesource.com/c/go/+/399539 +Reviewed-by: Ian Lance Taylor +Run-TryBot: Ian Lance Taylor +TryBot-Result: Gopher Robot +(cherry picked from commit f66925e854e71e0c54b581885380a490d7afa30c) +Reviewed-on: https://go-review.googlesource.com/c/go/+/401078 +Auto-Submit: Tatiana Bradley +Run-TryBot: Tatiana Bradley +Run-TryBot: Damien Neil +Auto-Submit: Damien Neil +Reviewed-by: Tatiana Bradley + +Reference:https://go-review.googlesource.com/c/go/+/401078/ +Conflict:NA +--- + src/syscall/syscall_linux.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go +index dfce3d0a4b..3387f3bdc2 100644 +--- a/src/syscall/syscall_linux.go ++++ b/src/syscall/syscall_linux.go +@@ -109,7 +109,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + gid = Getgid() + } + +- if uint32(gid) == st.Gid || isGroupMember(gid) { ++ if uint32(gid) == st.Gid || isGroupMember(int(st.Gid)) { + fmode = (st.Mode >> 3) & 7 + } else { + fmode = st.Mode & 7 +-- +2.30.2 + diff --git a/golang.spec b/golang.spec index 943a4ff..9ebf77f 100644 --- a/golang.spec +++ b/golang.spec @@ -66,7 +66,7 @@ Name: golang Version: 1.17.3 -Release: 6 +Release: 7 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -169,6 +169,8 @@ Patch6013: 0013-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch Patch6014: 0014-release-branch.go1.17-crypto-tls-randomly-generate-t.patch Patch6015: 0015-release-branch.go1.17-crypto-rand-properly-handle-la.patch Patch6016: 0016-release-branch.go1.17-math-big-check-buffer-lengths-.patch +Patch6017: 0017-path-filepath-do-not-remove-prefix-.-when-following-.patch +Patch6018: 0018-release-branch.go1.17-syscall-check-correct-group-in.patch ExclusiveArch: %{golang_arches} @@ -403,6 +405,12 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Thu Aug 18 2022 hanchao - 1.17.3-7 +- Type:CVE +- CVE:CVE-2022-29804,CVE-2022-29526 +- SUG:NA +- DESC: fix CVE-2022-29804,CVE-2022-29526 + * Mon Aug 8 2022 hanchao - 1.17.3-6 - Type:CVE - CVE:NA -- Gitee