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 0000000000000000000000000000000000000000..6f993e03193c56d30da7f26fdb8cbdc9c9e95ebd --- /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 0000000000000000000000000000000000000000..243596c90ead364fc953a1fd4144479adb812e12 --- /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/0002-syscall-expose-IfInfomsg.X__ifi_pad-on-s390x.patch b/0002-syscall-expose-IfInfomsg.X__ifi_pad-on-s390x.patch deleted file mode 100644 index 072440dd8a5cee630347de795e5ab1f96c2a0e2a..0000000000000000000000000000000000000000 --- a/0002-syscall-expose-IfInfomsg.X__ifi_pad-on-s390x.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 817407fc2d6a861e65086388766f58082d38bc0b Mon Sep 17 00:00:00 2001 -From: Michael Munday -Date: Tue, 17 Jan 2017 11:33:38 -0500 -Subject: [PATCH 2/3] syscall: expose IfInfomsg.X__ifi_pad on s390x - -Exposing this field on s390x improves compatibility with the other -linux architectures, all of which already expose it. - -Fixes #18628 and updates #18632. - -Change-Id: I08e8e1eb705f898cd8822f8bee0d61ce11d514b5 ---- - src/syscall/ztypes_linux_s390x.go | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/syscall/ztypes_linux_s390x.go b/src/syscall/ztypes_linux_s390x.go -index 63c4a83b19..b5894255df 100644 ---- a/src/syscall/ztypes_linux_s390x.go -+++ b/src/syscall/ztypes_linux_s390x.go -@@ -449,12 +449,12 @@ type RtAttr struct { - } - - type IfInfomsg struct { -- Family uint8 -- _ uint8 -- Type uint16 -- Index int32 -- Flags uint32 -- Change uint32 -+ Family uint8 -+ X__ifi_pad uint8 -+ Type uint16 -+ Index int32 -+ Flags uint32 -+ Change uint32 - } - - type IfAddrmsg struct { --- -2.14.3 - diff --git a/0003-golang-delete-pem-files.patch b/0003-golang-delete-pem-files.patch deleted file mode 100644 index a4114a192f5856aababbc7e97cf93fffc0125ed9..0000000000000000000000000000000000000000 --- a/0003-golang-delete-pem-files.patch +++ /dev/null @@ -1,44 +0,0 @@ -From de4a8f2f1c0e7c30dc5f54d19212eb29d01871ed Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Wed, 27 Nov 2019 10:46:52 +0800 -Subject: [PATCH 6/6] golang: delete pem files - -Signed-off-by: jingrui ---- - src/crypto/tls/testdata/example-cert.pem | 11 ----------- - src/crypto/tls/testdata/example-key.pem | 5 ----- - 2 files changed, 16 deletions(-) - delete mode 100644 src/crypto/tls/testdata/example-cert.pem - delete mode 100644 src/crypto/tls/testdata/example-key.pem - -diff --git a/src/crypto/tls/testdata/example-cert.pem b/src/crypto/tls/testdata/example-cert.pem -deleted file mode 100644 -index e0bf7db..0000000 ---- a/src/crypto/tls/testdata/example-cert.pem -+++ /dev/null -@@ -1,11 +0,0 @@ -------BEGIN CERTIFICATE----- --MIIBhTCCASugAwIBAgIQIRi6zePL6mKjOipn+dNuaTAKBggqhkjOPQQDAjASMRAw --DgYDVQQKEwdBY21lIENvMB4XDTE3MTAyMDE5NDMwNloXDTE4MTAyMDE5NDMwNlow --EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD0d --7VNhbWvZLWPuj/RtHFjvtJBEwOkhbN/BnnE8rnZR8+sbwnc/KhCk3FhnpHZnQz7B --5aETbbIgmuvewdjvSBSjYzBhMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr --BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdEQQiMCCCDmxvY2FsaG9zdDo1 --NDUzgg4xMjcuMC4wLjE6NTQ1MzAKBggqhkjOPQQDAgNIADBFAiEA2zpJEPQyz6/l --Wf86aX6PepsntZv2GYlA5UpabfT2EZICICpJ5h/iI+i341gBmLiAFQOyTDT+/wQc --6MF9+Yw1Yy0t -------END CERTIFICATE----- -diff --git a/src/crypto/tls/testdata/example-key.pem b/src/crypto/tls/testdata/example-key.pem -deleted file mode 100644 -index 104fb09..0000000 ---- a/src/crypto/tls/testdata/example-key.pem -+++ /dev/null -@@ -1,5 +0,0 @@ -------BEGIN EC PRIVATE KEY----- --MHcCAQEEIIrYSSNQFaA2Hwf1duRSxKtLYX5CB04fSeQ6tF1aY/PuoAoGCCqGSM49 --AwEHoUQDQgAEPR3tU2Fta9ktY+6P9G0cWO+0kETA6SFs38GecTyudlHz6xvCdz8q --EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA== -------END EC PRIVATE KEY----- --- -2.17.1 - 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 0000000000000000000000000000000000000000..64aee693f6998b6f9dd75f404673a048b9e74a24 --- /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/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 0000000000000000000000000000000000000000..6b9dd4b07c525c5e2263c1abb1c7c8fa199f8c92 --- /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/0004-syscall-implement-rawVforkSyscall-for-linux-arm64.patch b/0004-syscall-implement-rawVforkSyscall-for-linux-arm64.patch deleted file mode 100644 index bb83fced3b9a42c3a75e18d8b7bede43e96eee3d..0000000000000000000000000000000000000000 --- a/0004-syscall-implement-rawVforkSyscall-for-linux-arm64.patch +++ /dev/null @@ -1,101 +0,0 @@ -From fa95a1d8e7eda9ab90a7fd29785cad0ae7d816e2 Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Wed, 27 Nov 2019 09:54:22 +0800 -Subject: [PATCH 1/6] syscall: implement rawVforkSyscall for linux/arm64 - -This allows the use of CLONE_VFORK and CLONE_VM for fork/exec, preventing -"fork/exec ...: cannot allocate memory" failures from occuring when attempting -to execute commands from a Go process that has a large memory footprint. -Additionally, this should reduce the latency of fork/exec on linux/arm64. - -With CLONE_VM the child process shares the same memory with the parent -process. On its own this would lead to conflicting use of the same -memory, so CLONE_VFORK is used to suspend the parent process until the -child releases the memory when switching to the new program binary -via the exec syscall. When the parent process continues to run, one -has to consider the changes to memory that the child process did, -namely the return address of the syscall function needs to be restored -from a register. - -exec.Command() callers can start in a faster manner, as child process who -do exec commands job can be cloned faster via vfork than via fork on arm64. - -The same problem was addressed on linux/amd64 via issue #5838. - -Updates #31936 -Contributed by Howard Zhang and Bin Lu - -Change-Id: Ia99d81d877f564ec60d19f17e596276836576eaf -Reviewed-on: https://go-review.googlesource.com/c/go/+/189418 -Run-TryBot: Tobias Klauser -TryBot-Result: Gobot Gobot -Reviewed-by: Tobias Klauser -Reviewed-by: Cherry Zhang ---- - src/syscall/asm_linux_arm64.s | 23 +++++++++++++++++++++++ - src/syscall/exec_linux.go | 2 +- - src/syscall/syscall_linux_arm64.go | 4 +--- - 3 files changed, 25 insertions(+), 4 deletions(-) - -diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s -index 7edeafc..fb22f8d 100644 ---- a/src/syscall/asm_linux_arm64.s -+++ b/src/syscall/asm_linux_arm64.s -@@ -103,6 +103,29 @@ ok: - MOVD ZR, err+72(FP) // errno - RET - -+// func rawVforkSyscall(trap, a1 uintptr) (r1, err uintptr) -+TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-32 -+ MOVD a1+8(FP), R0 -+ MOVD $0, R1 -+ MOVD $0, R2 -+ MOVD $0, R3 -+ MOVD $0, R4 -+ MOVD $0, R5 -+ MOVD trap+0(FP), R8 // syscall entry -+ SVC -+ CMN $4095, R0 -+ BCC ok -+ MOVD $-1, R4 -+ MOVD R4, r1+16(FP) // r1 -+ NEG R0, R0 -+ MOVD R0, err+24(FP) // errno -+ RET -+ok: -+ MOVD R0, r1+16(FP) // r1 -+ MOVD ZR, err+24(FP) // errno -+ RET -+ -+ - // func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr); - TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48 - MOVD a1+8(FP), R0 -diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go -index a2242b2..3540d51 100644 ---- a/src/syscall/exec_linux.go -+++ b/src/syscall/exec_linux.go -@@ -196,7 +196,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att - } - } - -- hasRawVforkSyscall := runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "s390x" -+ hasRawVforkSyscall := runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64" - - // About to call fork. - // No more allocation or calls of non-assembly functions. -diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go -index 48ad0bb..89b2ab2 100644 ---- a/src/syscall/syscall_linux_arm64.go -+++ b/src/syscall/syscall_linux_arm64.go -@@ -154,6 +154,4 @@ const ( - SYS_EPOLL_WAIT = 1069 - ) - --func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) { -- panic("not implemented") --} -+func rawVforkSyscall(trap, a1 uintptr) (r1 uintptr, err Errno) --- -2.17.1 - 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 0000000000000000000000000000000000000000..98972340a918d866c0322d17b1c10068f2f57910 --- /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/0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch b/0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch deleted file mode 100644 index 5106d5a3b822adfc0c2c36e06eb9275a975a191d..0000000000000000000000000000000000000000 --- a/0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 8a755c0f0389dca42ec8caef0efa9b6ebe9d1e3c Mon Sep 17 00:00:00 2001 -From: Yuichi Nishiwaki -Date: Wed, 11 Sep 2019 02:26:02 +0000 -Subject: [PATCH 2/6] runtime: fix crash during VDSO calls on arm - -As discussed in #32912, a crash occurs when go runtime calls a VDSO function (say -__vdso_clock_gettime) and a signal arrives to that thread. -Since VDSO functions temporarily destroy the G register (R10), -Go functions asynchronously executed in that thread (i.e. Go's signal -handler) can try to load data from the destroyed G, which causes -segmentation fault. - -To fix the issue a guard is inserted in front of sigtrampgo, so that the control escapes from -signal handlers without touching G in case the signal occurred in the VDSO context. -The test case included in the patch is take from discussion in a relevant thread on github: -https://github.com/golang/go/issues/32912#issuecomment-517874531. -This patch not only fixes the issue on AArch64 but also that on 32bit ARM. - -Fixes #32912 - -Change-Id: I657472e54b7aa3c617fabc5019ce63aa4105624a -GitHub-Last-Rev: 28ce42c4a02a060f08c1b0dd1c9a392123fd2ee9 -GitHub-Pull-Request: golang/go#34030 -Reviewed-on: https://go-review.googlesource.com/c/go/+/192937 -Run-TryBot: Ian Lance Taylor -TryBot-Result: Gobot Gobot -Reviewed-by: Ian Lance Taylor ---- - src/runtime/crash_test.go | 9 +++++ - src/runtime/signal_unix.go | 27 ++++++++++--- - src/runtime/testdata/testprog/vdso.go | 55 +++++++++++++++++++++++++++ - src/runtime/vdso_linux.go | 1 + - 4 files changed, 86 insertions(+), 6 deletions(-) - create mode 100644 src/runtime/testdata/testprog/vdso.go - -diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go -index c54bb57..c2cab7c 100644 ---- a/src/runtime/crash_test.go -+++ b/src/runtime/crash_test.go -@@ -143,6 +143,15 @@ func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) - return exe, nil - } - -+func TestVDSO(t *testing.T) { -+ t.Parallel() -+ output := runTestProg(t, "testprog", "SignalInVDSO") -+ want := "success\n" -+ if output != want { -+ t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want); -+ } -+} -+ - var ( - staleRuntimeOnce sync.Once // guards init of staleRuntimeErr - staleRuntimeErr error -diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go -index ad51dc1..63fb07f 100644 ---- a/src/runtime/signal_unix.go -+++ b/src/runtime/signal_unix.go -@@ -274,6 +274,21 @@ func sigpipe() { - dieFromSignal(_SIGPIPE) - } - -+// sigFetchG fetches the value of G safely when running in a signal handler. -+// On some architectures, the g value may be clobbered when running in a VDSO. -+// See issue #32912. -+// -+//go:nosplit -+func sigFetchG(c *sigctxt) *g { -+ switch GOARCH { -+ case "arm", "arm64", "ppc64", "ppc64le": -+ if inVDSOPage(c.sigpc()) { -+ return nil -+ } -+ } -+ return getg() -+} -+ - // sigtrampgo is called from the signal handler function, sigtramp, - // written in assembly code. - // This is called by the signal handler, and the world may be stopped. -@@ -289,9 +304,9 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { - if sigfwdgo(sig, info, ctx) { - return - } -- g := getg() -+ c := &sigctxt{info, ctx} -+ g := sigFetchG(c) - if g == nil { -- c := &sigctxt{info, ctx} - if sig == _SIGPROF { - sigprofNonGoPC(c.sigpc()) - return -@@ -347,7 +362,6 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { - signalDuringFork(sig) - } - -- c := &sigctxt{info, ctx} - c.fixsigcode(sig) - sighandler(sig, info, ctx, g) - setg(g) -@@ -650,9 +664,10 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool { - return false - } - // Determine if the signal occurred inside Go code. We test that: -- // (1) we were in a goroutine (i.e., m.curg != nil), and -- // (2) we weren't in CGO. -- g := getg() -+ // (1) we weren't in VDSO page, -+ // (2) we were in a goroutine (i.e., m.curg != nil), and -+ // (3) we weren't in CGO. -+ g := sigFetchG(c) - if g != nil && g.m != nil && g.m.curg != nil && !g.m.incgo { - return false - } -diff --git a/src/runtime/testdata/testprog/vdso.go b/src/runtime/testdata/testprog/vdso.go -new file mode 100644 -index 0000000..6036f45 ---- /dev/null -+++ b/src/runtime/testdata/testprog/vdso.go -@@ -0,0 +1,55 @@ -+// Copyright 2019 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Invoke signal hander in the VDSO context (see issue 32912). -+ -+package main -+ -+import ( -+ "fmt" -+ "io/ioutil" -+ "os" -+ "runtime/pprof" -+ "time" -+) -+ -+func init() { -+ register("SignalInVDSO", signalInVDSO) -+} -+ -+func signalInVDSO() { -+ f, err := ioutil.TempFile("", "timeprofnow") -+ if err != nil { -+ fmt.Fprintln(os.Stderr, err) -+ os.Exit(2) -+ } -+ -+ if err := pprof.StartCPUProfile(f); err != nil { -+ fmt.Fprintln(os.Stderr, err) -+ os.Exit(2) -+ } -+ -+ t0 := time.Now() -+ t1 := t0 -+ // We should get a profiling signal 100 times a second, -+ // so running for 1 second should be sufficient. -+ for t1.Sub(t0) < time.Second { -+ t1 = time.Now() -+ } -+ -+ pprof.StopCPUProfile() -+ -+ name := f.Name() -+ if err := f.Close(); err != nil { -+ fmt.Fprintln(os.Stderr, err) -+ os.Exit(2) -+ } -+ -+ if err := os.Remove(name); err != nil { -+ fmt.Fprintln(os.Stderr, err) -+ os.Exit(2) -+ } -+ -+ fmt.Println("success"); -+} -diff --git a/src/runtime/vdso_linux.go b/src/runtime/vdso_linux.go -index 71ba4ce..8518276 100644 ---- a/src/runtime/vdso_linux.go -+++ b/src/runtime/vdso_linux.go -@@ -281,6 +281,7 @@ func vdsoauxv(tag, val uintptr) { - } - - // vdsoMarker reports whether PC is on the VDSO page. -+//go:nosplit - func inVDSOPage(pc uintptr) bool { - for _, k := range vdsoSymbolKeys { - if *k.ptr != 0 { --- -2.17.1 - 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 0000000000000000000000000000000000000000..23a903a9e5c421b420127404315fbf9983f6fde8 --- /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/0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch b/0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch deleted file mode 100644 index 717fcd96e70b5c1c5ef1ae804e7c5a042e0bc7f9..0000000000000000000000000000000000000000 --- a/0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 4717d9a1a21dfe051a14f033615218d833371d68 Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Wed, 27 Nov 2019 10:19:13 +0800 -Subject: [PATCH 3/6] runtime: save/fetch g register during VDSO on ARM and - ARM64 - -On ARM and ARM64, during a VDSO call, the g register may be -temporarily clobbered by the VDSO code. If a signal is received -during the execution of VDSO code, we may not find a valid g -reading the g register. In CL 192937, we conservatively assume -g is nil. But this approach has a problem: we cannot handle -the signal in this case. Further, if the signal is not a -profiling signal, we'll call badsignal, which calls needm, which -wants to get an extra m, but we don't have one in a non-cgo -binary, which cuases the program to hang. - -This is even more of a problem with async preemption, where we -will receive more signals than before. I ran into this problem -while working on async preemption support on ARM64. - -In this CL, before making a VDSO call, we save the g on the -gsignal stack. When we receive a signal, we will be running on -the gsignal stack, so we can fetch the g from there and move on. - -We probably want to do the same for PPC64. Currently we rely on -that the VDSO code doesn't actually clobber the g register, but -this is not guaranteed and we don't have control with. - -Idea from discussion with Dan Cross and Austin. - -Should fix #34391. - -Change-Id: Idbefc5e4c2f4373192c2be797be0140ae08b26e3 -Reviewed-on: https://go-review.googlesource.com/c/go/+/202759 -Run-TryBot: Cherry Zhang -Reviewed-by: Austin Clements ---- - src/os/signal/signal_test.go | 49 +++++++++++++++++++++++++++++++++++ - src/runtime/proc.go | 3 +++ - src/runtime/signal_unix.go | 24 ++++++++++++----- - src/runtime/sys_linux_arm.s | 32 +++++++++++++++++++++++ - src/runtime/sys_linux_arm64.s | 28 ++++++++++++++++++++ - 5 files changed, 129 insertions(+), 7 deletions(-) - -diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go -index 6ea59f4..c8274ea 100644 ---- a/src/os/signal/signal_test.go -+++ b/src/os/signal/signal_test.go -@@ -453,3 +453,52 @@ func atomicStopTestProgram() { - - os.Exit(0) - } -+ -+func TestTime(t *testing.T) { -+ // Test that signal works fine when we are in a call to get time, -+ // which on some platforms is using VDSO. See issue #34391. -+ dur := 3 * time.Second -+ if testing.Short() { -+ dur = 100 * time.Millisecond -+ } -+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) -+ done := make(chan bool) -+ finished := make(chan bool) -+ go func() { -+ sig := make(chan os.Signal, 1) -+ Notify(sig, syscall.SIGUSR1) -+ defer Stop(sig) -+ Loop: -+ for { -+ select { -+ case <-sig: -+ case <-done: -+ break Loop -+ } -+ } -+ finished <- true -+ }() -+ go func() { -+ Loop: -+ for { -+ select { -+ case <-done: -+ break Loop -+ default: -+ syscall.Kill(syscall.Getpid(), syscall.SIGUSR1) -+ runtime.Gosched() -+ } -+ } -+ finished <- true -+ }() -+ t0 := time.Now() -+ for t1 := t0; t1.Sub(t0) < dur; t1 = time.Now() { -+ } // hammering on getting time -+ close(done) -+ <-finished -+ <-finished -+ // When run with 'go test -cpu=1,2,4' SIGUSR1 from this test can slip -+ // into subsequent TestSignal() causing failure. -+ // Sleep for a while to reduce the possibility of the failure. -+ time.Sleep(10 * time.Millisecond) -+} -diff --git a/src/runtime/proc.go b/src/runtime/proc.go -index 93d329d..1487647 100644 ---- a/src/runtime/proc.go -+++ b/src/runtime/proc.go -@@ -3237,6 +3237,9 @@ func malg(stacksize int32) *g { - }) - newg.stackguard0 = newg.stack.lo + _StackGuard - newg.stackguard1 = ^uintptr(0) -+ // Clear the bottom word of the stack. We record g -+ // there on gsignal stack during VDSO on ARM and ARM64. -+ *(*uintptr)(unsafe.Pointer(newg.stack.lo)) = 0 - } - return newg - } -diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go -index 63fb07f..2cf1e3b 100644 ---- a/src/runtime/signal_unix.go -+++ b/src/runtime/signal_unix.go -@@ -280,13 +280,23 @@ func sigpipe() { - // - //go:nosplit - func sigFetchG(c *sigctxt) *g { -- switch GOARCH { -- case "arm", "arm64", "ppc64", "ppc64le": -- if inVDSOPage(c.sigpc()) { -- return nil -- } -- } -- return getg() -+ switch GOARCH { -+ case "arm", "arm64": -+ if inVDSOPage(c.sigpc()) { -+ // Before making a VDSO call we save the g to the bottom of the -+ // signal stack. Fetch from there. -+ // TODO: in efence mode, stack is sysAlloc'd, so this wouldn't -+ // work. -+ sp := getcallersp() -+ s := spanOf(sp) -+ if s != nil && s.state == mSpanManual && s.base() < sp && sp < s.limit { -+ gp := *(**g)(unsafe.Pointer(s.base())) -+ return gp -+ } -+ return nil -+ } -+ } -+ return getg() - } - - // sigtrampgo is called from the signal handler function, sigtramp, -diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s -index 9c73984..26e12a8 100644 ---- a/src/runtime/sys_linux_arm.s -+++ b/src/runtime/sys_linux_arm.s -@@ -246,7 +246,23 @@ noswitch: - CMP $0, R11 - B.EQ fallback - -+ // Store g on gsignal's stack, so if we receive a signal -+ // during VDSO code we can find the g. -+ // If we don't have a signal stack, we won't receive signal, -+ // so don't bother saving g. -+ MOVW m_gsignal(R5), R6 // g.m.gsignal -+ CMP $0, R6 -+ BEQ 3(PC) -+ MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo -+ MOVW g, (R6) -+ - BL (R11) -+ -+ CMP $0, R6 // R6 is unchanged by C code -+ BEQ 3(PC) -+ MOVW $0, R1 -+ MOVW R1, (R6) // clear g slot -+ - JMP finish - - fallback: -@@ -297,7 +313,23 @@ noswitch: - CMP $0, R11 - B.EQ fallback - -+ // Store g on gsignal's stack, so if we receive a signal -+ // during VDSO code we can find the g. -+ // If we don't have a signal stack, we won't receive signal, -+ // so don't bother saving g. -+ MOVW m_gsignal(R5), R6 // g.m.gsignal -+ CMP $0, R6 -+ BEQ 3(PC) -+ MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo -+ MOVW g, (R6) -+ - BL (R11) -+ -+ CMP $0, R6 // R6 is unchanged by C code -+ BEQ 3(PC) -+ MOVW $0, R1 -+ MOVW R1, (R6) // clear g slot -+ - JMP finish - - fallback: -diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s -index 2835b6c..fd40bf9 100644 ---- a/src/runtime/sys_linux_arm64.s -+++ b/src/runtime/sys_linux_arm64.s -@@ -207,7 +207,21 @@ noswitch: - MOVW $CLOCK_REALTIME, R0 - MOVD runtime·vdsoClockgettimeSym(SB), R2 - CBZ R2, fallback -+ -+ // Store g on gsignal's stack, so if we receive a signal -+ // during VDSO code we can find the g. -+ // If we don't have a signal stack, we won't receive signal, -+ // so don't bother saving g. -+ MOVD m_gsignal(R21), R22 // g.m.gsignal -+ CBZ R22, 3(PC) -+ MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo -+ MOVD g, (R22) -+ - BL (R2) -+ -+ CBZ R22, 2(PC) // R22 is unchanged by C code -+ MOVD ZR, (R22) // clear g slot -+ - B finish - - fallback: -@@ -250,7 +264,21 @@ noswitch: - MOVW $CLOCK_MONOTONIC, R0 - MOVD runtime·vdsoClockgettimeSym(SB), R2 - CBZ R2, fallback -+ -+ // Store g on gsignal's stack, so if we receive a signal -+ // during VDSO code we can find the g. -+ // If we don't have a signal stack, we won't receive signal, -+ // so don't bother saving g. -+ MOVD m_gsignal(R21), R22 // g.m.gsignal -+ CBZ R22, 3(PC) -+ MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo -+ MOVD g, (R22) -+ - BL (R2) -+ -+ CBZ R22, 2(PC) // R22 is unchanged by C code -+ MOVD ZR, (R22) // clear g slot -+ - B finish - - fallback: --- -2.17.1 - 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 0000000000000000000000000000000000000000..7fdcd6f86e68031ece6523d3aed9973202e91630 --- /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/0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch b/0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch deleted file mode 100644 index 0db9c7078fa0d164bd6c235f558e24816342f01c..0000000000000000000000000000000000000000 --- a/0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch +++ /dev/null @@ -1,179 +0,0 @@ -From fce0a59fc370634fcd7de8f8691e918cdf122f7d Mon Sep 17 00:00:00 2001 -From: Cherry Zhang -Date: Thu, 31 Oct 2019 10:32:31 -0400 -Subject: [PATCH 4/6] runtime: don't fetch G from signal stack when using cgo - -When using cgo, we save G to TLS, and when a signal happens, we -load G from TLS in sigtramp. This should give us a valid G. Don't -try to fetch from the signal stack. In particular, C code may -change the signal stack or call our signal handler directly (e.g. -TSAN), so we are not necessarily running on the original gsignal -stack where we saved G. - -Also skip saving G on the signal stack when using cgo. - -Updates #35249. - -Change-Id: I40749ce6682709bd4ebfdfd9f23bd0f317fc197d -Reviewed-on: https://go-review.googlesource.com/c/go/+/204519 -Reviewed-by: Ian Lance Taylor ---- - src/runtime/signal_unix.go | 8 +++++--- - src/runtime/sys_linux_arm.s | 30 ++++++++++++++++++++++-------- - src/runtime/sys_linux_arm64.s | 26 ++++++++++++++++++++------ - 3 files changed, 47 insertions(+), 17 deletions(-) - -diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go -index 2cf1e3b..721edb5 100644 ---- a/src/runtime/signal_unix.go -+++ b/src/runtime/signal_unix.go -@@ -282,9 +282,11 @@ func sigpipe() { - func sigFetchG(c *sigctxt) *g { - switch GOARCH { - case "arm", "arm64": -- if inVDSOPage(c.sigpc()) { -- // Before making a VDSO call we save the g to the bottom of the -- // signal stack. Fetch from there. -+ if !iscgo && inVDSOPage(c.sigpc()) { -+ // When using cgo, we save the g on TLS and load it from there -+ // in sigtramp. Just use that. -+ // Otherwise, before making a VDSO call we save the g to the -+ // bottom of the signal stack. Fetch from there. - // TODO: in efence mode, stack is sysAlloc'd, so this wouldn't - // work. - sp := getcallersp() -diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s -index 26e12a8..a47ac5f 100644 ---- a/src/runtime/sys_linux_arm.s -+++ b/src/runtime/sys_linux_arm.s -@@ -250,21 +250,28 @@ noswitch: - // during VDSO code we can find the g. - // If we don't have a signal stack, we won't receive signal, - // so don't bother saving g. -+ // When using cgo, we already saved g on TLS, also don't save -+ // g here. -+ MOVB runtime·iscgo(SB), R6 -+ CMP $0, R6 -+ BNE nosaveg - MOVW m_gsignal(R5), R6 // g.m.gsignal - CMP $0, R6 -- BEQ 3(PC) -+ BEQ nosaveg - MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo - MOVW g, (R6) - - BL (R11) - -- CMP $0, R6 // R6 is unchanged by C code -- BEQ 3(PC) - MOVW $0, R1 -- MOVW R1, (R6) // clear g slot -+ MOVW R1, (R6) // clear g slot, R6 is unchanged by C code - - JMP finish - -+nosaveg: -+ BL (R11) -+ JMP finish -+ - fallback: - MOVW $SYS_clock_gettime, R7 - SWI $0 -@@ -317,21 +324,28 @@ noswitch: - // during VDSO code we can find the g. - // If we don't have a signal stack, we won't receive signal, - // so don't bother saving g. -+ // When using cgo, we already saved g on TLS, also don't save -+ // g here. -+ MOVB runtime·iscgo(SB), R6 -+ CMP $0, R6 -+ BNE nosaveg - MOVW m_gsignal(R5), R6 // g.m.gsignal - CMP $0, R6 -- BEQ 3(PC) -+ BEQ nosaveg - MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo - MOVW g, (R6) - - BL (R11) - -- CMP $0, R6 // R6 is unchanged by C code -- BEQ 3(PC) - MOVW $0, R1 -- MOVW R1, (R6) // clear g slot -+ MOVW R1, (R6) // clear g slot, R6 is unchanged by C code - - JMP finish - -+nosaveg: -+ BL (R11) -+ JMP finish -+ - fallback: - MOVW $SYS_clock_gettime, R7 - SWI $0 -diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s -index fd40bf9..94c93ca 100644 ---- a/src/runtime/sys_linux_arm64.s -+++ b/src/runtime/sys_linux_arm64.s -@@ -212,18 +212,25 @@ noswitch: - // during VDSO code we can find the g. - // If we don't have a signal stack, we won't receive signal, - // so don't bother saving g. -+ // When using cgo, we already saved g on TLS, also don't save -+ // g here. -+ MOVBU runtime·iscgo(SB), R22 -+ CBNZ R22, nosaveg - MOVD m_gsignal(R21), R22 // g.m.gsignal -- CBZ R22, 3(PC) -+ CBZ R22, nosaveg - MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo - MOVD g, (R22) - - BL (R2) - -- CBZ R22, 2(PC) // R22 is unchanged by C code -- MOVD ZR, (R22) // clear g slot -+ MOVD ZR, (R22) // clear g slot, R22 is unchanged by C code - - B finish - -+nosaveg: -+ BL (R2) -+ B finish -+ - fallback: - MOVD $SYS_clock_gettime, R8 - SVC -@@ -269,18 +276,25 @@ noswitch: - // during VDSO code we can find the g. - // If we don't have a signal stack, we won't receive signal, - // so don't bother saving g. -+ // When using cgo, we already saved g on TLS, also don't save -+ // g here. -+ MOVBU runtime·iscgo(SB), R22 -+ CBNZ R22, nosaveg - MOVD m_gsignal(R21), R22 // g.m.gsignal -- CBZ R22, 3(PC) -+ CBZ R22, nosaveg - MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo - MOVD g, (R22) - - BL (R2) - -- CBZ R22, 2(PC) // R22 is unchanged by C code -- MOVD ZR, (R22) // clear g slot -+ MOVD ZR, (R22) // clear g slot, R22 is unchanged by C code - - B finish - -+nosaveg: -+ BL (R2) -+ B finish -+ - fallback: - MOVD $SYS_clock_gettime, R8 - SVC --- -2.17.1 - 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 0000000000000000000000000000000000000000..077af1523521e89770af7211afd05a3cf1422ca7 --- /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/0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch b/0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch deleted file mode 100644 index e71d11fd6dd51b1f63fbdab1b03293b5792021c0..0000000000000000000000000000000000000000 --- a/0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch +++ /dev/null @@ -1,107 +0,0 @@ -From e83074ea52287115b85002a6b72137c72f6d7ecc Mon Sep 17 00:00:00 2001 -From: Cherry Zhang -Date: Sun, 10 Nov 2019 13:18:06 -0500 -Subject: [PATCH 5/6] runtime: don't save G during VDSO if we're handling - signal - -On some platforms (currently ARM and ARM64), when calling into -VDSO we store the G to the gsignal stack, if there is one, so if -we receive a signal during VDSO we can find the G. - -If we receive a signal during VDSO, and within the signal handler -we call nanotime again (e.g. when handling profiling signal), -we'll save/clear the G slot on the gsignal stack again, which -clobbers the original saved G. If we receive a second signal -during the same VDSO execution, we will fetch a nil G, which will -lead to bad things such as deadlock. - -Don't save G if we're calling VDSO code from the gsignal stack. -Saving G is not necessary as we won't receive a nested signal. - -Fixes #35473. - -Change-Id: Ibfd8587a3c70c2f1533908b056e81b94d75d65a5 -Reviewed-on: https://go-review.googlesource.com/c/go/+/206397 -Run-TryBot: Cherry Zhang -TryBot-Result: Gobot Gobot -Reviewed-by: Bryan C. Mills ---- - src/runtime/sys_linux_arm.s | 8 ++++++++ - src/runtime/sys_linux_arm64.s | 8 ++++++++ - 2 files changed, 16 insertions(+) - -diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s -index a47ac5f..577faac 100644 ---- a/src/runtime/sys_linux_arm.s -+++ b/src/runtime/sys_linux_arm.s -@@ -252,12 +252,16 @@ noswitch: - // so don't bother saving g. - // When using cgo, we already saved g on TLS, also don't save - // g here. -+ // Also don't save g if we are already on the signal stack. -+ // We won't get a nested signal. - MOVB runtime·iscgo(SB), R6 - CMP $0, R6 - BNE nosaveg - MOVW m_gsignal(R5), R6 // g.m.gsignal - CMP $0, R6 - BEQ nosaveg -+ CMP g, R6 -+ BEQ nosaveg - MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo - MOVW g, (R6) - -@@ -326,12 +330,16 @@ noswitch: - // so don't bother saving g. - // When using cgo, we already saved g on TLS, also don't save - // g here. -+ // Also don't save g if we are already on the signal stack. -+ // We won't get a nested signal. - MOVB runtime·iscgo(SB), R6 - CMP $0, R6 - BNE nosaveg - MOVW m_gsignal(R5), R6 // g.m.gsignal - CMP $0, R6 - BEQ nosaveg -+ CMP g, R6 -+ BEQ nosaveg - MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo - MOVW g, (R6) - -diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s -index 94c93ca..a076744 100644 ---- a/src/runtime/sys_linux_arm64.s -+++ b/src/runtime/sys_linux_arm64.s -@@ -214,10 +214,14 @@ noswitch: - // so don't bother saving g. - // When using cgo, we already saved g on TLS, also don't save - // g here. -+ // Also don't save g if we are already on the signal stack. -+ // We won't get a nested signal. - MOVBU runtime·iscgo(SB), R22 - CBNZ R22, nosaveg - MOVD m_gsignal(R21), R22 // g.m.gsignal - CBZ R22, nosaveg -+ CMP g, R22 -+ BEQ nosaveg - MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo - MOVD g, (R22) - -@@ -278,10 +282,14 @@ noswitch: - // so don't bother saving g. - // When using cgo, we already saved g on TLS, also don't save - // g here. -+ // Also don't save g if we are already on the signal stack. -+ // We won't get a nested signal. - MOVBU runtime·iscgo(SB), R22 - CBNZ R22, nosaveg - MOVD m_gsignal(R21), R22 // g.m.gsignal - CBZ R22, nosaveg -+ CMP g, R22 -+ BEQ nosaveg - MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo - MOVD g, (R22) - --- -2.17.1 - diff --git a/0009-release-branch.go1.13-net-http-don-t-cache-http2.err.patch b/0009-release-branch.go1.13-net-http-don-t-cache-http2.err.patch deleted file mode 100644 index fc12ac4bf10f2706120885af09ac1103eda56929..0000000000000000000000000000000000000000 --- a/0009-release-branch.go1.13-net-http-don-t-cache-http2.err.patch +++ /dev/null @@ -1,130 +0,0 @@ -From b2df6bf225859f82b3f69d471e1c99b72c208ec3 Mon Sep 17 00:00:00 2001 -From: Brad Fitzpatrick -Date: Fri, 18 Oct 2019 20:45:33 +0000 -Subject: [PATCH] [release-branch.go1.13] net/http: don't cache - http2.erringRoundTripper connections - -Fixes #35087 -Updates #34978 - -Change-Id: I3baf1392ba7366ae6628889c47c343ef702ec438 -Reviewed-on: https://go-review.googlesource.com/c/go/+/202078 -Reviewed-by: Bryan C. Mills -Run-TryBot: Brad Fitzpatrick -TryBot-Result: Gobot Gobot -(cherry picked from commit 88186e5e232625f9c91d639e0cb90a88c6cf1172) -Reviewed-on: https://go-review.googlesource.com/c/go/+/202642 -Reviewed-by: Emmanuel Odeke ---- - src/net/http/transport.go | 9 +++- - src/net/http/transport_test.go | 75 ++++++++++++++++++++++++++++++++++ - 2 files changed, 82 insertions(+), 2 deletions(-) - -diff --git a/src/net/http/transport.go b/src/net/http/transport.go -index caa4bdc36f..b46c4e7066 100644 ---- a/src/net/http/transport.go -+++ b/src/net/http/transport.go -@@ -537,10 +537,15 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) { - if err == nil { - return resp, nil - } -- if http2isNoCachedConnError(err) { -+ -+ // Failed. Clean up and determine whether to retry. -+ -+ _, isH2DialError := pconn.alt.(http2erringRoundTripper) -+ if http2isNoCachedConnError(err) || isH2DialError { - t.removeIdleConn(pconn) - t.decConnsPerHost(pconn.cacheKey) -- } else if !pconn.shouldRetryRequest(req, err) { -+ } -+ if !pconn.shouldRetryRequest(req, err) { - // Issue 16465: return underlying net.Conn.Read error from peek, - // as we've historically done. - if e, ok := err.(transportReadFromServerError); ok { -diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go -index e43c8956ee..f8c13a7091 100644 ---- a/src/net/http/transport_test.go -+++ b/src/net/http/transport_test.go -@@ -5719,3 +5719,78 @@ func TestInvalidHeaderResponse(t *testing.T) { - t.Errorf(`bad "Foo " header value: %q, want %q`, v, "bar") - } - } -+ -+// breakableConn is a net.Conn wrapper with a Write method -+// that will fail when its brokenState is true. -+type breakableConn struct { -+ net.Conn -+ *brokenState -+} -+ -+type brokenState struct { -+ sync.Mutex -+ broken bool -+} -+ -+func (w *breakableConn) Write(b []byte) (n int, err error) { -+ w.Lock() -+ defer w.Unlock() -+ if w.broken { -+ return 0, errors.New("some write error") -+ } -+ return w.Conn.Write(b) -+} -+ -+// Issue 34978: don't cache a broken HTTP/2 connection -+func TestDontCacheBrokenHTTP2Conn(t *testing.T) { -+ cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {}), optQuietLog) -+ defer cst.close() -+ -+ var brokenState brokenState -+ -+ cst.tr.Dial = func(netw, addr string) (net.Conn, error) { -+ c, err := net.Dial(netw, addr) -+ if err != nil { -+ t.Errorf("unexpected Dial error: %v", err) -+ return nil, err -+ } -+ return &breakableConn{c, &brokenState}, err -+ } -+ -+ const numReqs = 5 -+ var gotConns uint32 // atomic -+ for i := 1; i <= numReqs; i++ { -+ brokenState.Lock() -+ brokenState.broken = false -+ brokenState.Unlock() -+ -+ // doBreak controls whether we break the TCP connection after the TLS -+ // handshake (before the HTTP/2 handshake). We test a few failures -+ // in a row followed by a final success. -+ doBreak := i != numReqs -+ -+ ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{ -+ GotConn: func(info httptrace.GotConnInfo) { -+ atomic.AddUint32(&gotConns, 1) -+ }, -+ TLSHandshakeDone: func(cfg tls.ConnectionState, err error) { -+ brokenState.Lock() -+ defer brokenState.Unlock() -+ if doBreak { -+ brokenState.broken = true -+ } -+ }, -+ }) -+ req, err := NewRequestWithContext(ctx, "GET", cst.ts.URL, nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ _, err = cst.c.Do(req) -+ if doBreak != (err != nil) { -+ t.Errorf("for iteration %d, doBreak=%v; unexpected error %v", i, doBreak, err) -+ } -+ } -+ if got, want := atomic.LoadUint32(&gotConns), 1; int(got) != want { -+ t.Errorf("GotConn calls = %v; want %v", got, want) -+ } -+} --- -2.17.1 - 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 0000000000000000000000000000000000000000..13f56a5ce339c494603c9e8c1a7c47bcf8a318f4 --- /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.13-net-http-fix-Server.ConnContex.patch b/0010-release-branch.go1.13-net-http-fix-Server.ConnContex.patch deleted file mode 100644 index c23adb8a9ade1bc752743efa2cdf3d40b5996a27..0000000000000000000000000000000000000000 --- a/0010-release-branch.go1.13-net-http-fix-Server.ConnContex.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 94b6eec5dc639e87f0e2f739cfd257a432160881 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Roman=20Koll=C3=A1r?= -Date: Thu, 21 Nov 2019 22:25:52 +0000 -Subject: [PATCH] [release-branch.go1.13] net/http: fix Server.ConnContext - modifying context for all new connections - -Updates #35750 -Fixes #35765 - -Change-Id: I65d38cfc5ddd66131777e104c269cc3559b2471d -GitHub-Last-Rev: 953fdfd49b2be665be43f8148d2a6180dae3b91c -GitHub-Pull-Request: golang/go#35751 -Reviewed-on: https://go-review.googlesource.com/c/go/+/208318 -Reviewed-by: Brad Fitzpatrick -Run-TryBot: Brad Fitzpatrick -TryBot-Result: Gobot Gobot -(cherry picked from commit bbbc6589dfbc05be2bfa59f51c20f9eaa8d0c531) -Reviewed-on: https://go-review.googlesource.com/c/go/+/208235 -Reviewed-by: Bryan C. Mills ---- - src/net/http/serve_test.go | 33 +++++++++++++++++++++++++++++++++ - src/net/http/server.go | 7 ++++--- - 2 files changed, 37 insertions(+), 3 deletions(-) - -diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go -index 1d1449aa65..90f112b2ee 100644 ---- a/src/net/http/serve_test.go -+++ b/src/net/http/serve_test.go -@@ -6121,6 +6121,39 @@ func TestServerContextsHTTP2(t *testing.T) { - } - } - -+// Issue 35750: check ConnContext not modifying context for other connections -+func TestConnContextNotModifyingAllContexts(t *testing.T) { -+ setParallel(t) -+ defer afterTest(t) -+ type connKey struct{} -+ ts := httptest.NewUnstartedServer(HandlerFunc(func(rw ResponseWriter, r *Request) { -+ rw.Header().Set("Connection", "close") -+ })) -+ ts.Config.ConnContext = func(ctx context.Context, c net.Conn) context.Context { -+ if got := ctx.Value(connKey{}); got != nil { -+ t.Errorf("in ConnContext, unexpected context key = %#v", got) -+ } -+ return context.WithValue(ctx, connKey{}, "conn") -+ } -+ ts.Start() -+ defer ts.Close() -+ -+ var res *Response -+ var err error -+ -+ res, err = ts.Client().Get(ts.URL) -+ if err != nil { -+ t.Fatal(err) -+ } -+ res.Body.Close() -+ -+ res, err = ts.Client().Get(ts.URL) -+ if err != nil { -+ t.Fatal(err) -+ } -+ res.Body.Close() -+} -+ - // Issue 30710: ensure that as per the spec, a server responds - // with 501 Not Implemented for unsupported transfer-encodings. - func TestUnsupportedTransferEncodingsReturn501(t *testing.T) { -diff --git a/src/net/http/server.go b/src/net/http/server.go -index 95a5eabaa2..8252e45aca 100644 ---- a/src/net/http/server.go -+++ b/src/net/http/server.go -@@ -2915,16 +2915,17 @@ func (srv *Server) Serve(l net.Listener) error { - } - return e - } -+ connCtx := ctx - if cc := srv.ConnContext; cc != nil { -- ctx = cc(ctx, rw) -- if ctx == nil { -+ connCtx = cc(connCtx, rw) -+ if connCtx == nil { - panic("ConnContext returned nil") - } - } - tempDelay = 0 - c := srv.newConn(rw) - c.setState(c.rwc, StateNew) // before Serve can return -- go c.serve(ctx) -+ go c.serve(connCtx) - } - } - --- -2.17.1 - 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 0000000000000000000000000000000000000000..c1943787ed4deeb3a6687cd4fd560c68b9dbac4c --- /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.13-runtime-fix-textOff-for-multip.patch b/0011-release-branch.go1.13-runtime-fix-textOff-for-multip.patch deleted file mode 100644 index 7de5e384adff3449d133ea5c1a4d376be4094d14..0000000000000000000000000000000000000000 --- a/0011-release-branch.go1.13-runtime-fix-textOff-for-multip.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 6eee9903c7f970defbc0c9770397790b2bed5709 Mon Sep 17 00:00:00 2001 -From: Lynn Boger -Date: Mon, 28 Oct 2019 09:29:40 -0400 -Subject: [PATCH] [release-branch.go1.13] runtime: fix textOff for multiple - text sections - -If a compilation has multiple text sections, code in -textOff must compare the offset argument against the range -for each text section to determine which one it is in. -The comparison looks like this: - -if uintptr(off) >= sectaddr && uintptr(off) <= sectaddr+sectlen - -If the off value being compared is equal to sectaddr+sectlen then it -is not within the range of the text section but after it. The -comparison should be just '<'. - -Fixes #35211 - -Change-Id: I114633fd734563d38f4e842dd884c6c239f73c95 -Reviewed-on: https://go-review.googlesource.com/c/go/+/203817 -Run-TryBot: Lynn Boger -TryBot-Result: Gobot Gobot -Reviewed-by: Ian Lance Taylor -Reviewed-by: Cherry Zhang -(cherry picked from commit 0ae9389609f23dc905c58fc2ad7bcc16b770f337) -Reviewed-on: https://go-review.googlesource.com/c/go/+/203819 -Run-TryBot: Carlos Amedee -Reviewed-by: Keith Randall ---- - src/runtime/type.go | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/runtime/type.go b/src/runtime/type.go -index 660b45ef39..5ae3c4b09e 100644 ---- a/src/runtime/type.go -+++ b/src/runtime/type.go -@@ -287,7 +287,7 @@ func (t *_type) textOff(off textOff) unsafe.Pointer { - for i := range md.textsectmap { - sectaddr := md.textsectmap[i].vaddr - sectlen := md.textsectmap[i].length -- if uintptr(off) >= sectaddr && uintptr(off) <= sectaddr+sectlen { -+ if uintptr(off) >= sectaddr && uintptr(off) < sectaddr+sectlen { - res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr) - break - } --- -2.17.1 - 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 0000000000000000000000000000000000000000..661634ac3dabe484b61c160c12218f3fb5a04700 --- /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.13-runtime-ensure-memmove-write-p.patch b/0012-release-branch.go1.13-runtime-ensure-memmove-write-p.patch deleted file mode 100644 index 20c49cd48b435409998d6e9840bdb1dc4d1d809b..0000000000000000000000000000000000000000 --- a/0012-release-branch.go1.13-runtime-ensure-memmove-write-p.patch +++ /dev/null @@ -1,126 +0,0 @@ -From acc723af2646200d13f76ffde80b000c4095074a Mon Sep 17 00:00:00 2001 -From: Cherry Zhang -Date: Fri, 27 Dec 2019 12:02:00 -0500 -Subject: [PATCH] [release-branch.go1.13] runtime: ensure memmove write pointer - atomically on ARM64 - -If a pointer write is not atomic, if the GC is running -concurrently, it may observe a partially updated pointer, which -may point to unallocated or already dead memory. Most pointer -writes, like the store instructions generated by the compiler, -are already atomic. But we still need to be careful in places -like memmove. In memmove, we don't know which bits are pointers -(or too expensive to query), so we ensure that all aligned -pointer-sized units are written atomically. - -Fixes #36361. -Updates #36101. - -Change-Id: I1b3ca24c6b1ac8a8aaf9ee470115e9a89ec1b00b -Reviewed-on: https://go-review.googlesource.com/c/go/+/212626 -Reviewed-by: Austin Clements -(cherry picked from commit ffbc02761abb47106ce88e09290a31513b5f6c8a) -Reviewed-on: https://go-review.googlesource.com/c/go/+/213683 -Run-TryBot: Cherry Zhang -TryBot-Result: Gobot Gobot ---- - src/runtime/memmove_arm64.s | 42 +++++++++++++++++++++++++++++++++++++----- - 1 file changed, 37 insertions(+), 5 deletions(-) - -diff --git a/src/runtime/memmove_arm64.s b/src/runtime/memmove_arm64.s -index ac29f94..cedb018 100644 ---- a/src/runtime/memmove_arm64.s -+++ b/src/runtime/memmove_arm64.s -@@ -22,7 +22,7 @@ check: - CMP R3, R4 - BLT backward - -- // Copying forward proceeds by copying R7/8 words then copying R6 bytes. -+ // Copying forward proceeds by copying R7/32 quadwords then R6 <= 31 tail bytes. - // R3 and R4 are advanced as we copy. - - // (There may be implementations of armv8 where copying by bytes until -@@ -30,11 +30,12 @@ check: - // optimization, but the on the one tested so far (xgene) it did not - // make a significance difference.) - -- CBZ R7, noforwardlarge // Do we need to do any doubleword-by-doubleword copying? -+ CBZ R7, noforwardlarge // Do we need to do any quadword copying? - - ADD R3, R7, R9 // R9 points just past where we copy by word - - forwardlargeloop: -+ // Copy 32 bytes at a time. - LDP.P 32(R4), (R8, R10) - STP.P (R8, R10), 32(R3) - LDP -16(R4), (R11, R12) -@@ -43,10 +44,26 @@ forwardlargeloop: - CBNZ R7, forwardlargeloop - - noforwardlarge: -- CBNZ R6, forwardtail // Do we need to do any byte-by-byte copying? -+ CBNZ R6, forwardtail // Do we need to copy any tail bytes? - RET - - forwardtail: -+ // There are R6 <= 31 bytes remaining to copy. -+ // This is large enough to still contain pointers, -+ // which must be copied atomically. -+ // Copy the next 16 bytes, then 8 bytes, then any remaining bytes. -+ TBZ $4, R6, 3(PC) // write 16 bytes if R6&16 != 0 -+ LDP.P 16(R4), (R8, R10) -+ STP.P (R8, R10), 16(R3) -+ -+ TBZ $3, R6, 3(PC) // write 8 bytes if R6&8 != 0 -+ MOVD.P 8(R4), R8 -+ MOVD.P R8, 8(R3) -+ -+ AND $7, R6 -+ CBNZ R6, 2(PC) -+ RET -+ - ADD R3, R6, R9 // R9 points just past the destination memory - - forwardtailloop: -@@ -90,7 +107,7 @@ copy1: - RET - - backward: -- // Copying backwards proceeds by copying R6 bytes then copying R7/8 words. -+ // Copying backwards first copies R6 <= 31 tail bytes, then R7/32 quadwords. - // R3 and R4 are advanced to the end of the destination/source buffers - // respectively and moved back as we copy. - -@@ -99,13 +116,28 @@ backward: - - CBZ R6, nobackwardtail // Do we need to do any byte-by-byte copying? - -- SUB R6, R3, R9 // R9 points at the lowest destination byte that should be copied by byte. -+ AND $7, R6, R12 -+ CBZ R12, backwardtaillarge -+ -+ SUB R12, R3, R9 // R9 points at the lowest destination byte that should be copied by byte. - backwardtailloop: -+ // Copy sub-pointer-size tail. - MOVBU.W -1(R4), R8 - MOVBU.W R8, -1(R3) - CMP R9, R3 - BNE backwardtailloop - -+backwardtaillarge: -+ // Do 8/16-byte write if possible. -+ // See comment at forwardtail. -+ TBZ $3, R6, 3(PC) -+ MOVD.W -8(R4), R8 -+ MOVD.W R8, -8(R3) -+ -+ TBZ $4, R6, 3(PC) -+ LDP.W -16(R4), (R8, R10) -+ STP.W (R8, R10), -16(R3) -+ - nobackwardtail: - CBNZ R7, backwardlarge // Do we need to do any doubleword-by-doubleword copying? - RET --- -1.8.3.1 - 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 0000000000000000000000000000000000000000..9be1eea8260baee823f1d033a0493f36a0efb8e1 --- /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-drop-hard-code-cert.patch b/0013-drop-hard-code-cert.patch deleted file mode 100644 index 1af1acc73a346d0e546ae1f4be3c0f0bd6c55841..0000000000000000000000000000000000000000 --- a/0013-drop-hard-code-cert.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 2720067ebfb7568792bb0c8fe3fbf095c89b77a9 Mon Sep 17 00:00:00 2001 -From: jingrui -Date: Tue, 17 Mar 2020 17:43:33 +0800 -Subject: [PATCH] drop hard-code cert - -Signed-off-by: jingrui ---- - src/crypto/x509/test-file.crt | 32 --------------------------- - src/crypto/x509/testdata/test-dir.crt | 31 -------------------------- - src/net/http/internal/testcert.go | 31 ++------------------------ - 3 files changed, 2 insertions(+), 92 deletions(-) - delete mode 100644 src/crypto/x509/test-file.crt - delete mode 100644 src/crypto/x509/testdata/test-dir.crt - -diff --git a/src/crypto/x509/test-file.crt b/src/crypto/x509/test-file.crt -deleted file mode 100644 -index caa83b9..0000000 ---- a/src/crypto/x509/test-file.crt -+++ /dev/null -@@ -1,32 +0,0 @@ -------BEGIN CERTIFICATE----- --MIIFbTCCA1WgAwIBAgIJAN338vEmMtLsMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNV --BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz --dHMxEjAQBgNVBAMMCXRlc3QtZmlsZTAeFw0xNzAyMDEyMzUyMDhaFw0yNzAxMzAy --MzUyMDhaME0xCzAJBgNVBAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYD --VQQKDAxHb2xhbmcgVGVzdHMxEjAQBgNVBAMMCXRlc3QtZmlsZTCCAiIwDQYJKoZI --hvcNAQEBBQADggIPADCCAgoCggIBAPMGiLjdiffQo3Xc8oUe7wsDhSaAJFOhO6Qs --i0xYrYl7jmCuz9rGD2fdgk5cLqGazKuQ6fIFzHXFU2BKs4CWXt9KO0KFEhfvZeuW --jG5d7C1ZUiuKOrPqjKVu8SZtFPc7y7Ke7msXzY+Z2LLyiJJ93LCMq4+cTSGNXVlI --KqUxhxeoD5/QkUPyQy/ilu3GMYfx/YORhDP6Edcuskfj8wRh1UxBejP8YPMvI6St --cE2GkxoEGqDWnQ/61F18te6WI3MD29tnKXOkXVhnSC+yvRLljotW2/tAhHKBG4tj --iQWT5Ri4Wrw2tXxPKRLsVWc7e1/hdxhnuvYpXkWNhKsm002jzkFXlzfEwPd8nZdw --5aT6gPUBN2AAzdoqZI7E200i0orEF7WaSoMfjU1tbHvExp3vyAPOfJ5PS2MQ6W03 --Zsy5dTVH+OBH++rkRzQCFcnIv/OIhya5XZ9KX9nFPgBEP7Xq2A+IjH7B6VN/S/bv --8lhp2V+SQvlew9GttKC4hKuPsl5o7+CMbcqcNUdxm9gGkN8epGEKCuix97bpNlxN --fHZxHE5+8GMzPXMkCD56y5TNKR6ut7JGHMPtGl5lPCLqzG/HzYyFgxsDfDUu2B0A --GKj0lGpnLfGqwhs2/s3jpY7+pcvVQxEpvVTId5byDxu1ujP4HjO/VTQ2P72rE8Ft --C6J2Av0tAgMBAAGjUDBOMB0GA1UdDgQWBBTLT/RbyfBB/Pa07oBnaM+QSJPO9TAf --BgNVHSMEGDAWgBTLT/RbyfBB/Pa07oBnaM+QSJPO9TAMBgNVHRMEBTADAQH/MA0G --CSqGSIb3DQEBCwUAA4ICAQB3sCntCcQwhMgRPPyvOCMyTcQ/Iv+cpfxz2Ck14nlx --AkEAH2CH0ov5GWTt07/ur3aa5x+SAKi0J3wTD1cdiw4U/6Uin6jWGKKxvoo4IaeK --SbM8w/6eKx6UbmHx7PA/eRABY9tTlpdPCVgw7/o3WDr03QM+IAtatzvaCPPczake --pbdLwmBZB/v8V+6jUajy6jOgdSH0PyffGnt7MWgDETmNC6p/Xigp5eh+C8Fb4NGT --xgHES5PBC+sruWp4u22bJGDKTvYNdZHsnw/CaKQWNsQqwisxa3/8N5v+PCff/pxl --r05pE3PdHn9JrCl4iWdVlgtiI9BoPtQyDfa/OEFaScE8KYR8LxaAgdgp3zYncWls --BpwQ6Y/A2wIkhlD9eEp5Ib2hz7isXOs9UwjdriKqrBXqcIAE5M+YIk3+KAQKxAtd --4YsK3CSJ010uphr12YKqlScj4vuKFjuOtd5RyyMIxUG3lrrhAu2AzCeKCLdVgA8+ --75FrYMApUdvcjp4uzbBoED4XRQlx9kdFHVbYgmE/+yddBYJM8u4YlgAL0hW2/D8p --z9JWIfxVmjJnBnXaKGBuiUyZ864A3PJndP6EMMo7TzS2CDnfCYuJjvI0KvDjFNmc --rQA04+qfMSEz3nmKhbbZu4eYLzlADhfH8tT4GMtXf71WLA5AUHGf2Y4+HIHTsmHG --vQ== -------END CERTIFICATE----- -diff --git a/src/crypto/x509/testdata/test-dir.crt b/src/crypto/x509/testdata/test-dir.crt -deleted file mode 100644 -index b7fc9c5..0000000 ---- a/src/crypto/x509/testdata/test-dir.crt -+++ /dev/null -@@ -1,31 +0,0 @@ -------BEGIN CERTIFICATE----- --MIIFazCCA1OgAwIBAgIJAL8a/lsnspOqMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV --BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz --dHMxETAPBgNVBAMMCHRlc3QtZGlyMB4XDTE3MDIwMTIzNTAyN1oXDTI3MDEzMDIz --NTAyN1owTDELMAkGA1UEBhMCVUsxEzARBgNVBAgMClRlc3QtU3RhdGUxFTATBgNV --BAoMDEdvbGFuZyBUZXN0czERMA8GA1UEAwwIdGVzdC1kaXIwggIiMA0GCSqGSIb3 --DQEBAQUAA4ICDwAwggIKAoICAQDzBoi43Yn30KN13PKFHu8LA4UmgCRToTukLItM --WK2Je45grs/axg9n3YJOXC6hmsyrkOnyBcx1xVNgSrOAll7fSjtChRIX72Xrloxu --XewtWVIrijqz6oylbvEmbRT3O8uynu5rF82Pmdiy8oiSfdywjKuPnE0hjV1ZSCql --MYcXqA+f0JFD8kMv4pbtxjGH8f2DkYQz+hHXLrJH4/MEYdVMQXoz/GDzLyOkrXBN --hpMaBBqg1p0P+tRdfLXuliNzA9vbZylzpF1YZ0gvsr0S5Y6LVtv7QIRygRuLY4kF --k+UYuFq8NrV8TykS7FVnO3tf4XcYZ7r2KV5FjYSrJtNNo85BV5c3xMD3fJ2XcOWk --+oD1ATdgAM3aKmSOxNtNItKKxBe1mkqDH41NbWx7xMad78gDznyeT0tjEOltN2bM --uXU1R/jgR/vq5Ec0AhXJyL/ziIcmuV2fSl/ZxT4ARD+16tgPiIx+welTf0v27/JY --adlfkkL5XsPRrbSguISrj7JeaO/gjG3KnDVHcZvYBpDfHqRhCgrosfe26TZcTXx2 --cRxOfvBjMz1zJAg+esuUzSkerreyRhzD7RpeZTwi6sxvx82MhYMbA3w1LtgdABio --9JRqZy3xqsIbNv7N46WO/qXL1UMRKb1UyHeW8g8btboz+B4zv1U0Nj+9qxPBbQui --dgL9LQIDAQABo1AwTjAdBgNVHQ4EFgQUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwHwYD --VR0jBBgwFoAUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwDAYDVR0TBAUwAwEB/zANBgkq --hkiG9w0BAQsFAAOCAgEAvEVnUYsIOt87rggmLPqEueynkuQ+562M8EDHSQl82zbe --xDCxeg3DvPgKb+RvaUdt1362z/szK10SoeMgx6+EQLoV9LiVqXwNqeYfixrhrdw3 --ppAhYYhymdkbUQCEMHypmXP1vPhAz4o8Bs+eES1M+zO6ErBiD7SqkmBElT+GixJC --6epC9ZQFs+dw3lPlbiZSsGE85sqc3VAs0/JgpL/pb1/Eg4s0FUhZD2C2uWdSyZGc --g0/v3aXJCp4j/9VoNhI1WXz3M45nysZIL5OQgXymLqJElQa1pZ3Wa4i/nidvT4AT --Xlxc/qijM8set/nOqp7hVd5J0uG6qdwLRILUddZ6OpXd7ZNi1EXg+Bpc7ehzGsDt --3UFGzYXDjxYnK2frQfjLS8stOQIqSrGthW6x0fdkVx0y8BByvd5J6+JmZl4UZfzA --m99VxXSt4B9x6BvnY7ktzcFDOjtuLc4B/7yg9fv1eQuStA4cHGGAttsCg1X/Kx8W --PvkkeH0UWDZ9vhH9K36703z89da6MWF+bz92B0+4HoOmlVaXRkvblsNaynJnL0LC --Ayry7QBxuh5cMnDdRwJB3AVJIiJ1GVpb7aGvBOnx+s2lwRv9HWtghb+cbwwktx1M --JHyBf3GZNSWTpKY7cD8V+NnBv3UuioOVVo+XAU4LF/bYUjdRpxWADJizNtZrtFo= -------END CERTIFICATE----- -diff --git a/src/net/http/internal/testcert.go b/src/net/http/internal/testcert.go -index 2284a83..a33d06b 100644 ---- a/src/net/http/internal/testcert.go -+++ b/src/net/http/internal/testcert.go -@@ -10,36 +10,9 @@ import "strings" - // "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT. - // generated from src/crypto/tls: - // go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h --var LocalhostCert = []byte(`-----BEGIN CERTIFICATE----- --MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS --MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw --MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB --iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4 --iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul --rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO --BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw --AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA --AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9 --tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs --h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM --fblo6RBxUQ== -------END CERTIFICATE-----`) -+var LocalhostCert = []byte(``) - - // LocalhostKey is the private key for localhostCert. --var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY----- --MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9 --SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB --l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB --AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet --3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb --uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H --qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp --jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY --fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U --fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU --y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX --qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo --f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA== -------END RSA TESTING KEY-----`)) -+var LocalhostKey = []byte(testingKey(``)) - - func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } --- -2.17.1 - 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 0000000000000000000000000000000000000000..7a54a71ea1789a38b6e07405b4c2d47766b75f08 --- /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 0000000000000000000000000000000000000000..f8f418a62b7f0a81fcd8bd8ae61ed498bf433228 --- /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 0000000000000000000000000000000000000000..092814022de625d9ed3205ff3821ec33ae0f0350 --- /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/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 0000000000000000000000000000000000000000..78f8090c522ff73f635f567a3ce02cd46d419180 --- /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/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 0000000000000000000000000000000000000000..0f44f3850d75025e402eebca56b103c2e0751d04 --- /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 0000000000000000000000000000000000000000..23872111deb09ff6cf9b92db33cd86301899934d --- /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/0019-release-branch.go1.18-net-http-update-bundled-golang.patch b/0019-release-branch.go1.18-net-http-update-bundled-golang.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb88ffd8f25334b9b38efb3a899543927ce056ad --- /dev/null +++ b/0019-release-branch.go1.18-net-http-update-bundled-golang.patch @@ -0,0 +1,99 @@ +From b2058191785138021b635f609de3d5f651ec02cd Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Mon, 22 Aug 2022 16:21:02 -0700 +Subject: [PATCH] [release-branch.go1.18] net/http: update bundled + golang.org/x/net/http2 + +Disable cmd/internal/moddeps test, since this update includes PRIVATE +track fixes. + +Fixes CVE-2022-27664 +Fixes #53977 +For #54658. + +Change-Id: I84b0b8f61e49e15ef55ef8d738730107a3cf849b +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1554415 +Reviewed-by: Roland Shoemaker +Reviewed-by: Tatiana Bradley +Reviewed-on: https://go-review.googlesource.com/c/go/+/428635 +Reviewed-by: Tatiana Bradley +Run-TryBot: Michael Knyszek +TryBot-Result: Gopher Robot +Reviewed-by: Carlos Amedee + +Conflict:NA +Reference:https://go-review.googlesource.com/c/go/+/428635/ +--- + src/cmd/internal/moddeps/moddeps_test.go | 2 ++ + src/net/http/h2_bundle.go | 21 +++++++++++++-------- + 2 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/src/cmd/internal/moddeps/moddeps_test.go b/src/cmd/internal/moddeps/moddeps_test.go +index 56c3b2585c..3306e29431 100644 +--- a/src/cmd/internal/moddeps/moddeps_test.go ++++ b/src/cmd/internal/moddeps/moddeps_test.go +@@ -34,6 +34,8 @@ import ( + // See issues 36852, 41409, and 43687. + // (Also see golang.org/issue/27348.) + func TestAllDependencies(t *testing.T) { ++ t.Skip("TODO(#53977): 1.18.5 contains unreleased changes from vendored modules") ++ + goBin := testenv.GoToolPath(t) + + // Ensure that all packages imported within GOROOT +diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go +index 1b73da7f21..d7e2f764c8 100644 +--- a/src/net/http/h2_bundle.go ++++ b/src/net/http/h2_bundle.go +@@ -3339,10 +3339,11 @@ func (s http2SettingID) String() string { + // name (key). See httpguts.ValidHeaderName for the base rules. + // + // Further, http2 says: +-// "Just as in HTTP/1.x, header field names are strings of ASCII +-// characters that are compared in a case-insensitive +-// fashion. However, header field names MUST be converted to +-// lowercase prior to their encoding in HTTP/2. " ++// ++// "Just as in HTTP/1.x, header field names are strings of ASCII ++// characters that are compared in a case-insensitive ++// fashion. However, header field names MUST be converted to ++// lowercase prior to their encoding in HTTP/2. " + func http2validWireHeaderFieldName(v string) bool { + if len(v) == 0 { + return false +@@ -3533,8 +3534,8 @@ func (s *http2sorter) SortStrings(ss []string) { + // validPseudoPath reports whether v is a valid :path pseudo-header + // value. It must be either: + // +-// *) a non-empty string starting with '/' +-// *) the string '*', for OPTIONS requests. ++// *) a non-empty string starting with '/' ++// *) the string '*', for OPTIONS requests. + // + // For now this is only used a quick check for deciding when to clean + // up Opaque URLs before sending requests from the Transport. +@@ -4999,6 +5000,9 @@ func (sc *http2serverConn) startGracefulShutdownInternal() { + func (sc *http2serverConn) goAway(code http2ErrCode) { + sc.serveG.check() + if sc.inGoAway { ++ if sc.goAwayCode == http2ErrCodeNo { ++ sc.goAwayCode = code ++ } + return + } + sc.inGoAway = true +@@ -6211,8 +6215,9 @@ func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) { + // prior to the headers being written. If the set of trailers is fixed + // or known before the header is written, the normal Go trailers mechanism + // is preferred: +-// https://golang.org/pkg/net/http/#ResponseWriter +-// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers ++// ++// https://golang.org/pkg/net/http/#ResponseWriter ++// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers + const http2TrailerPrefix = "Trailer:" + + // promoteUndeclaredTrailers permits http.Handlers to set trailers +-- +2.30.2 + diff --git a/0020-release-branch.go1.18-regexp-limit-size-of-parsed-re.patch b/0020-release-branch.go1.18-regexp-limit-size-of-parsed-re.patch new file mode 100644 index 0000000000000000000000000000000000000000..436d179e6bff17d7fa124142248dc997ba68947d --- /dev/null +++ b/0020-release-branch.go1.18-regexp-limit-size-of-parsed-re.patch @@ -0,0 +1,386 @@ +From 8b3a5d153b7b255bafd1a82d61505088356d0458 Mon Sep 17 00:00:00 2001 +From: Russ Cox +Date: Wed, 28 Sep 2022 11:18:51 -0400 +Subject: [PATCH] regexp: limit size of parsed regexps + +Set a 128 MB limit on the amount of space used by []syntax.Inst +in the compiled form corresponding to a given regexp. + +Also set a 128 MB limit on the rune storage in the *syntax.Regexp +tree itself. + +Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting this issue. + +Fixes CVE-2022-41715. +Updates #55949. +Fixes #55950. + +Change-Id: Ia656baed81564436368cf950e1c5409752f28e1b +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1592136 +TryBot-Result: Security TryBots +Reviewed-by: Damien Neil +Run-TryBot: Roland Shoemaker +Reviewed-by: Julie Qiu +Reviewed-on: https://go-review.googlesource.com/c/go/+/438501 +Run-TryBot: Carlos Amedee +Reviewed-by: Carlos Amedee +Reviewed-by: Dmitri Shuralyov +TryBot-Result: Gopher Robot +Reviewed-by: Dmitri Shuralyov +--- + src/regexp/syntax/parse.go | 222 +++++++++++++++++++++++++++++++- + src/regexp/syntax/parse_test.go | 11 +- + 2 files changed, 224 insertions(+), 9 deletions(-) + +diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go +index 7b40309..67254d6 100644 +--- a/src/regexp/syntax/parse.go ++++ b/src/regexp/syntax/parse.go +@@ -43,6 +43,7 @@ const ( + ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator" + ErrTrailingBackslash ErrorCode = "trailing backslash at end of expression" + ErrUnexpectedParen ErrorCode = "unexpected )" ++ ErrNestingDepth ErrorCode = "expression nests too deeply" + ) + + func (e ErrorCode) String() string { +@@ -76,13 +77,63 @@ const ( + opVerticalBar + ) + ++// maxHeight is the maximum height of a regexp parse tree. ++// It is somewhat arbitrarily chosen, but the idea is to be large enough ++// that no one will actually hit in real use but at the same time small enough ++// that recursion on the Regexp tree will not hit the 1GB Go stack limit. ++// The maximum amount of stack for a single recursive frame is probably ++// closer to 1kB, so this could potentially be raised, but it seems unlikely ++// that people have regexps nested even this deeply. ++// We ran a test on Google's C++ code base and turned up only ++// a single use case with depth > 100; it had depth 128. ++// Using depth 1000 should be plenty of margin. ++// As an optimization, we don't even bother calculating heights ++// until we've allocated at least maxHeight Regexp structures. ++const maxHeight = 1000 ++ ++// maxSize is the maximum size of a compiled regexp in Insts. ++// It too is somewhat arbitrarily chosen, but the idea is to be large enough ++// to allow significant regexps while at the same time small enough that ++// the compiled form will not take up too much memory. ++// 128 MB is enough for a 3.3 million Inst structures, which roughly ++// corresponds to a 3.3 MB regexp. ++const ( ++ maxSize = 128 << 20 / instSize ++ instSize = 5 * 8 // byte, 2 uint32, slice is 5 64-bit words ++) ++ ++// maxRunes is the maximum number of runes allowed in a regexp tree ++// counting the runes in all the nodes. ++// Ignoring character classes p.numRunes is always less than the length of the regexp. ++// Character classes can make it much larger: each \pL adds 1292 runes. ++// 128 MB is enough for 32M runes, which is over 26k \pL instances. ++// Note that repetitions do not make copies of the rune slices, ++// so \pL{1000} is only one rune slice, not 1000. ++// We could keep a cache of character classes we've seen, ++// so that all the \pL we see use the same rune list, ++// but that doesn't remove the problem entirely: ++// consider something like [\pL01234][\pL01235][\pL01236]...[\pL^&*()]. ++// And because the Rune slice is exposed directly in the Regexp, ++// there is not an opportunity to change the representation to allow ++// partial sharing between different character classes. ++// So the limit is the best we can do. ++const ( ++ maxRunes = 128 << 20 / runeSize ++ runeSize = 4 // rune is int32 ++) ++ + type parser struct { + flags Flags // parse mode flags + stack []*Regexp // stack of parsed expressions + free *Regexp + numCap int // number of capturing groups seen + wholeRegexp string +- tmpClass []rune // temporary char class work space ++ tmpClass []rune // temporary char class work space ++ numRegexp int // number of regexps allocated ++ numRunes int // number of runes in char classes ++ repeats int64 // product of all repetitions seen ++ height map[*Regexp]int // regexp height, for height limit check ++ size map[*Regexp]int64 // regexp compiled size, for size limit check + } + + func (p *parser) newRegexp(op Op) *Regexp { +@@ -92,20 +143,155 @@ func (p *parser) newRegexp(op Op) *Regexp { + *re = Regexp{} + } else { + re = new(Regexp) ++ p.numRegexp++ + } + re.Op = op + return re + } + + func (p *parser) reuse(re *Regexp) { ++ if p.height != nil { ++ delete(p.height, re) ++ } + re.Sub0[0] = p.free + p.free = re + } + ++func (p *parser) checkLimits(re *Regexp) { ++ if p.numRunes > maxRunes { ++ panic(ErrInternalError) ++ } ++ p.checkSize(re) ++ p.checkHeight(re) ++} ++ ++func (p *parser) checkSize(re *Regexp) { ++ if p.size == nil { ++ // We haven't started tracking size yet. ++ // Do a relatively cheap check to see if we need to start. ++ // Maintain the product of all the repeats we've seen ++ // and don't track if the total number of regexp nodes ++ // we've seen times the repeat product is in budget. ++ if p.repeats == 0 { ++ p.repeats = 1 ++ } ++ if re.Op == OpRepeat { ++ n := re.Max ++ if n == -1 { ++ n = re.Min ++ } ++ if n <= 0 { ++ n = 1 ++ } ++ if int64(n) > maxSize/p.repeats { ++ p.repeats = maxSize ++ } else { ++ p.repeats *= int64(n) ++ } ++ } ++ if int64(p.numRegexp) < maxSize/p.repeats { ++ return ++ } ++ ++ // We need to start tracking size. ++ // Make the map and belatedly populate it ++ // with info about everything we've constructed so far. ++ p.size = make(map[*Regexp]int64) ++ for _, re := range p.stack { ++ p.checkSize(re) ++ } ++ } ++ ++ if p.calcSize(re, true) > maxSize { ++ panic(ErrInternalError) ++ } ++} ++ ++func (p *parser) calcSize(re *Regexp, force bool) int64 { ++ if !force { ++ if size, ok := p.size[re]; ok { ++ return size ++ } ++ } ++ ++ var size int64 ++ switch re.Op { ++ case OpLiteral: ++ size = int64(len(re.Rune)) ++ case OpCapture, OpStar: ++ // star can be 1+ or 2+; assume 2 pessimistically ++ size = 2 + p.calcSize(re.Sub[0], false) ++ case OpPlus, OpQuest: ++ size = 1 + p.calcSize(re.Sub[0], false) ++ case OpConcat: ++ for _, sub := range re.Sub { ++ size += p.calcSize(sub, false) ++ } ++ case OpAlternate: ++ for _, sub := range re.Sub { ++ size += p.calcSize(sub, false) ++ } ++ if len(re.Sub) > 1 { ++ size += int64(len(re.Sub)) - 1 ++ } ++ case OpRepeat: ++ sub := p.calcSize(re.Sub[0], false) ++ if re.Max == -1 { ++ if re.Min == 0 { ++ size = 2 + sub // x* ++ } else { ++ size = 1 + int64(re.Min)*sub // xxx+ ++ } ++ break ++ } ++ // x{2,5} = xx(x(x(x)?)?)? ++ size = int64(re.Max)*sub + int64(re.Max-re.Min) ++ } ++ ++ if size < 1 { ++ size = 1 ++ } ++ p.size[re] = size ++ return size ++} ++ ++func (p *parser) checkHeight(re *Regexp) { ++ if p.numRegexp < maxHeight { ++ return ++ } ++ if p.height == nil { ++ p.height = make(map[*Regexp]int) ++ for _, re := range p.stack { ++ p.checkHeight(re) ++ } ++ } ++ if p.calcHeight(re, true) > maxHeight { ++ panic(ErrNestingDepth) ++ } ++} ++ ++func (p *parser) calcHeight(re *Regexp, force bool) int { ++ if !force { ++ if h, ok := p.height[re]; ok { ++ return h ++ } ++ } ++ h := 1 ++ for _, sub := range re.Sub { ++ hsub := p.calcHeight(sub, false) ++ if h < 1+hsub { ++ h = 1 + hsub ++ } ++ } ++ p.height[re] = h ++ return h ++} ++ + // Parse stack manipulation. + + // push pushes the regexp re onto the parse stack and returns the regexp. + func (p *parser) push(re *Regexp) *Regexp { ++ p.numRunes += len(re.Rune) + if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] { + // Single rune. + if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) { +@@ -137,6 +323,7 @@ func (p *parser) push(re *Regexp) *Regexp { + } + + p.stack = append(p.stack, re) ++ p.checkLimits(re) + return re + } + +@@ -246,6 +433,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) ( + re.Sub = re.Sub0[:1] + re.Sub[0] = sub + p.stack[n-1] = re ++ p.checkLimits(re) + + if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) { + return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]} +@@ -390,12 +578,16 @@ func (p *parser) collapse(subs []*Regexp, op Op) *Regexp { + // frees (passes to p.reuse) any removed *Regexps. + // + // For example, +-// ABC|ABD|AEF|BCX|BCY ++// ++// ABC|ABD|AEF|BCX|BCY ++// + // simplifies by literal prefix extraction to +-// A(B(C|D)|EF)|BC(X|Y) ++// ++// A(B(C|D)|EF)|BC(X|Y) ++// + // which simplifies by character class introduction to +-// A(B[CD]|EF)|BC[XY] + // ++// A(B[CD]|EF)|BC[XY] + func (p *parser) factor(sub []*Regexp) []*Regexp { + if len(sub) < 2 { + return sub +@@ -449,6 +641,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp { + + for j := start; j < i; j++ { + sub[j] = p.removeLeadingString(sub[j], len(str)) ++ p.checkLimits(sub[j]) + } + suffix := p.collapse(sub[start:i], OpAlternate) // recurse + +@@ -506,6 +699,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp { + for j := start; j < i; j++ { + reuse := j != start // prefix came from sub[start] + sub[j] = p.removeLeadingRegexp(sub[j], reuse) ++ p.checkLimits(sub[j]) + } + suffix := p.collapse(sub[start:i], OpAlternate) // recurse + +@@ -693,6 +887,23 @@ func literalRegexp(s string, flags Flags) *Regexp { + // Flags, and returns a regular expression parse tree. The syntax is + // described in the top-level comment. + func Parse(s string, flags Flags) (*Regexp, error) { ++ return parse(s, flags) ++} ++ ++func parse(s string, flags Flags) (_ *Regexp, err error) { ++ defer func() { ++ switch r := recover(); r { ++ default: ++ panic(r) ++ case nil: ++ // ok ++ case ErrInternalError: // too big ++ err = &Error{Code: ErrInternalError, Expr: s} ++ case ErrNestingDepth: ++ err = &Error{Code: ErrNestingDepth, Expr: s} ++ } ++ }() ++ + if flags&Literal != 0 { + // Trivial parser for literal string. + if err := checkUTF8(s); err != nil { +@@ -704,7 +915,6 @@ func Parse(s string, flags Flags) (*Regexp, error) { + // Otherwise, must do real work. + var ( + p parser +- err error + c rune + op Op + lastRepeat string +@@ -1733,7 +1943,7 @@ func appendClass(r []rune, x []rune) []rune { + return r + } + +-// appendFolded returns the result of appending the case folding of the class x to the class r. ++// appendFoldedClass returns the result of appending the case folding of the class x to the class r. + func appendFoldedClass(r []rune, x []rune) []rune { + for i := 0; i < len(x); i += 2 { + r = appendFoldedRange(r, x[i], x[i+1]) +diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go +index 5581ba1..6044da6 100644 +--- a/src/regexp/syntax/parse_test.go ++++ b/src/regexp/syntax/parse_test.go +@@ -479,10 +479,15 @@ var invalidRegexps = []string{ + `(?P<>a)`, + `[a-Z]`, + `(?i)[a-Z]`, +- `a{100000}`, +- `a{100000,}`, +- "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", + `\Q\E*`, ++ `a{100000}`, // too much repetition ++ `a{100000,}`, // too much repetition ++ "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", // too much repetition ++ strings.Repeat("(", 1000) + strings.Repeat(")", 1000), // too deep ++ strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000), // too deep ++ "(" + strings.Repeat("(xx?)", 1000) + "){1000}", // too long ++ strings.Repeat("(xx?){1000}", 1000), // too long ++ strings.Repeat(`\pL`, 27000), // too many runes + } + + var onlyPerl = []string{ +-- +2.33.0 + diff --git a/0021-release-branch.go1.18-net-http-httputil-avoid-query-.patch b/0021-release-branch.go1.18-net-http-httputil-avoid-query-.patch new file mode 100644 index 0000000000000000000000000000000000000000..b07cf56be34db31d457fe07f457477c33be3122b --- /dev/null +++ b/0021-release-branch.go1.18-net-http-httputil-avoid-query-.patch @@ -0,0 +1,174 @@ +From 51a477dc4f1130d53e66cd2003de0bac40e5e2be Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Thu, 22 Sep 2022 13:32:00 -0700 +Subject: [PATCH 2/3] [release-branch.go1.18] net/http/httputil: avoid query + parameter smuggling + +Query parameter smuggling occurs when a proxy's interpretation +of query parameters differs from that of a downstream server. +Change ReverseProxy to avoid forwarding ignored query parameters. + +Remove unparsable query parameters from the outbound request + + * if req.Form != nil after calling ReverseProxy.Director; and + * before calling ReverseProxy.Rewrite. + +This change preserves the existing behavior of forwarding the +raw query untouched if a Director hook does not parse the query +by calling Request.ParseForm (possibly indirectly). + +Fixes #55842 +For #54663 +For CVE-2022-2880 + +Change-Id: If1621f6b0e73a49d79059dae9e6b256e0ff18ca9 +Reviewed-on: https://go-review.googlesource.com/c/go/+/432976 +Reviewed-by: Roland Shoemaker +Reviewed-by: Brad Fitzpatrick +TryBot-Result: Gopher Robot +Run-TryBot: Damien Neil +(cherry picked from commit 7c84234142149bd24a4096c6cab691d3593f3431) +Reviewed-on: https://go-review.googlesource.com/c/go/+/433695 +Reviewed-by: Dmitri Shuralyov +Reviewed-by: Dmitri Shuralyov +--- + src/net/http/httputil/reverseproxy.go | 36 +++++++++++ + src/net/http/httputil/reverseproxy_test.go | 74 ++++++++++++++++++++++ + 2 files changed, 110 insertions(+) + +diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go +index 8b63368386..c76eec6987 100644 +--- a/src/net/http/httputil/reverseproxy.go ++++ b/src/net/http/httputil/reverseproxy.go +@@ -249,6 +249,9 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + } + + p.Director(outreq) ++ if outreq.Form != nil { ++ outreq.URL.RawQuery = cleanQueryParams(outreq.URL.RawQuery) ++ } + outreq.Close = false + + reqUpType := upgradeType(outreq.Header) +@@ -628,3 +631,36 @@ func (c switchProtocolCopier) copyToBackend(errc chan<- error) { + _, err := io.Copy(c.backend, c.user) + errc <- err + } ++ ++func cleanQueryParams(s string) string { ++ reencode := func(s string) string { ++ v, _ := url.ParseQuery(s) ++ return v.Encode() ++ } ++ for i := 0; i < len(s); { ++ switch s[i] { ++ case ';': ++ return reencode(s) ++ case '%': ++ if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) { ++ return reencode(s) ++ } ++ i += 3 ++ default: ++ i++ ++ } ++ } ++ return s ++} ++ ++func ishex(c byte) bool { ++ switch { ++ case '0' <= c && c <= '9': ++ return true ++ case 'a' <= c && c <= 'f': ++ return true ++ case 'A' <= c && c <= 'F': ++ return true ++ } ++ return false ++} +diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go +index 4b6ad77a29..8c0a4f136b 100644 +--- a/src/net/http/httputil/reverseproxy_test.go ++++ b/src/net/http/httputil/reverseproxy_test.go +@@ -1517,3 +1517,77 @@ func TestJoinURLPath(t *testing.T) { + } + } + } ++ ++const ( ++ testWantsCleanQuery = true ++ testWantsRawQuery = false ++) ++ ++func TestReverseProxyQueryParameterSmugglingDirectorDoesNotParseForm(t *testing.T) { ++ testReverseProxyQueryParameterSmuggling(t, testWantsRawQuery, func(u *url.URL) *ReverseProxy { ++ proxyHandler := NewSingleHostReverseProxy(u) ++ oldDirector := proxyHandler.Director ++ proxyHandler.Director = func(r *http.Request) { ++ oldDirector(r) ++ } ++ return proxyHandler ++ }) ++} ++ ++func TestReverseProxyQueryParameterSmugglingDirectorParsesForm(t *testing.T) { ++ testReverseProxyQueryParameterSmuggling(t, testWantsCleanQuery, func(u *url.URL) *ReverseProxy { ++ proxyHandler := NewSingleHostReverseProxy(u) ++ oldDirector := proxyHandler.Director ++ proxyHandler.Director = func(r *http.Request) { ++ // Parsing the form causes ReverseProxy to remove unparsable ++ // query parameters before forwarding. ++ r.FormValue("a") ++ oldDirector(r) ++ } ++ return proxyHandler ++ }) ++} ++ ++func testReverseProxyQueryParameterSmuggling(t *testing.T, wantCleanQuery bool, newProxy func(*url.URL) *ReverseProxy) { ++ const content = "response_content" ++ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.Write([]byte(r.URL.RawQuery)) ++ })) ++ defer backend.Close() ++ backendURL, err := url.Parse(backend.URL) ++ if err != nil { ++ t.Fatal(err) ++ } ++ proxyHandler := newProxy(backendURL) ++ frontend := httptest.NewServer(proxyHandler) ++ defer frontend.Close() ++ ++ // Don't spam output with logs of queries containing semicolons. ++ backend.Config.ErrorLog = log.New(io.Discard, "", 0) ++ frontend.Config.ErrorLog = log.New(io.Discard, "", 0) ++ ++ for _, test := range []struct { ++ rawQuery string ++ cleanQuery string ++ }{{ ++ rawQuery: "a=1&a=2;b=3", ++ cleanQuery: "a=1", ++ }, { ++ rawQuery: "a=1&a=%zz&b=3", ++ cleanQuery: "a=1&b=3", ++ }} { ++ res, err := frontend.Client().Get(frontend.URL + "?" + test.rawQuery) ++ if err != nil { ++ t.Fatalf("Get: %v", err) ++ } ++ defer res.Body.Close() ++ body, _ := io.ReadAll(res.Body) ++ wantQuery := test.rawQuery ++ if wantCleanQuery { ++ wantQuery = test.cleanQuery ++ } ++ if got, want := string(body), wantQuery; got != want { ++ t.Errorf("proxy forwarded raw query %q as %q, want %q", test.rawQuery, got, want) ++ } ++ } ++} +-- +2.33.0 + diff --git a/0022-release-branch.go1.18-archive-tar-limit-size-of-head.patch b/0022-release-branch.go1.18-archive-tar-limit-size-of-head.patch new file mode 100644 index 0000000000000000000000000000000000000000..550877a2761d619b88ba92186052542583d1ad5c --- /dev/null +++ b/0022-release-branch.go1.18-archive-tar-limit-size-of-head.patch @@ -0,0 +1,186 @@ +From 7dd44b287830fbb2256aceac4a36756b955c0279 Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Fri, 2 Sep 2022 20:45:18 -0700 +Subject: [PATCH] archive/tar: limit size of headers + +Set a 1MiB limit on special file blocks (PAX headers, GNU long names, +GNU link names), to avoid reading arbitrarily large amounts of data +into memory. + +Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting +this issue. + +Fixes CVE-2022-2879 +Updates #54853 +Fixes #55925 + +Change-Id: I85136d6ff1e0af101a112190e027987ab4335680 +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1565555 +Reviewed-by: Tatiana Bradley +Run-TryBot: Roland Shoemaker +Reviewed-by: Roland Shoemaker +(cherry picked from commit 6ee768cef6b82adf7a90dcf367a1699ef694f3b2) +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1590622 +Reviewed-by: Damien Neil +Reviewed-by: Julie Qiu +Reviewed-on: https://go-review.googlesource.com/c/go/+/438500 +Reviewed-by: Dmitri Shuralyov +Reviewed-by: Carlos Amedee +Reviewed-by: Dmitri Shuralyov +Run-TryBot: Carlos Amedee +TryBot-Result: Gopher Robot +--- + src/archive/tar/format.go | 4 ++++ + src/archive/tar/reader.go | 14 ++++++++++++-- + src/archive/tar/reader_test.go | 11 ++++++++++- + src/archive/tar/writer.go | 3 +++ + src/archive/tar/writer_test.go | 27 +++++++++++++++++++++++++++ + 5 files changed, 56 insertions(+), 3 deletions(-) + +diff --git a/src/archive/tar/format.go b/src/archive/tar/format.go +index cfe24a5..6642364 100644 +--- a/src/archive/tar/format.go ++++ b/src/archive/tar/format.go +@@ -143,6 +143,10 @@ const ( + blockSize = 512 // Size of each block in a tar stream + nameSize = 100 // Max length of the name field in USTAR format + prefixSize = 155 // Max length of the prefix field in USTAR format ++ ++ // Max length of a special file (PAX header, GNU long name or link). ++ // This matches the limit used by libarchive. ++ maxSpecialFileSize = 1 << 20 + ) + + // blockPadding computes the number of bytes needed to pad offset up to the +diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go +index 1b1d5b4..f645af8 100644 +--- a/src/archive/tar/reader.go ++++ b/src/archive/tar/reader.go +@@ -103,7 +103,7 @@ func (tr *Reader) next() (*Header, error) { + continue // This is a meta header affecting the next header + case TypeGNULongName, TypeGNULongLink: + format.mayOnlyBe(FormatGNU) +- realname, err := io.ReadAll(tr) ++ realname, err := readSpecialFile(tr) + if err != nil { + return nil, err + } +@@ -293,7 +293,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) { + // parsePAX parses PAX headers. + // If an extended header (type 'x') is invalid, ErrHeader is returned + func parsePAX(r io.Reader) (map[string]string, error) { +- buf, err := io.ReadAll(r) ++ buf, err := readSpecialFile(r) + if err != nil { + return nil, err + } +@@ -826,6 +826,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) { + return n, err + } + ++// readSpecialFile is like io.ReadAll except it returns ++// ErrFieldTooLong if more than maxSpecialFileSize is read. ++func readSpecialFile(r io.Reader) ([]byte, error) { ++ buf, err := io.ReadAll(io.LimitReader(r, maxSpecialFileSize+1)) ++ if len(buf) > maxSpecialFileSize { ++ return nil, ErrFieldTooLong ++ } ++ return buf, err ++} ++ + // discard skips n bytes in r, reporting an error if unable to do so. + func discard(r io.Reader, n int64) error { + // If possible, Seek to the last byte before the end of the data section. +diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go +index 789ddc1..5a644a4 100644 +--- a/src/archive/tar/reader_test.go ++++ b/src/archive/tar/reader_test.go +@@ -6,6 +6,7 @@ package tar + + import ( + "bytes" ++ "compress/bzip2" + "crypto/md5" + "errors" + "fmt" +@@ -243,6 +244,9 @@ func TestReader(t *testing.T) { + }, { + file: "testdata/pax-bad-hdr-file.tar", + err: ErrHeader, ++ }, { ++ file: "testdata/pax-bad-hdr-large.tar.bz2", ++ err: ErrFieldTooLong, + }, { + file: "testdata/pax-bad-mtime-file.tar", + err: ErrHeader, +@@ -625,9 +629,14 @@ func TestReader(t *testing.T) { + } + defer f.Close() + ++ var fr io.Reader = f ++ if strings.HasSuffix(v.file, ".bz2") { ++ fr = bzip2.NewReader(fr) ++ } ++ + // Capture all headers and checksums. + var ( +- tr = NewReader(f) ++ tr = NewReader(fr) + hdrs []*Header + chksums []string + rdbuf = make([]byte, 8) +diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go +index e80498d..893eac0 100644 +--- a/src/archive/tar/writer.go ++++ b/src/archive/tar/writer.go +@@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error { + flag = TypeXHeader + } + data := buf.String() ++ if len(data) > maxSpecialFileSize { ++ return ErrFieldTooLong ++ } + if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal { + return err // Global headers return here + } +diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go +index a00f02d..4e709e5 100644 +--- a/src/archive/tar/writer_test.go ++++ b/src/archive/tar/writer_test.go +@@ -1006,6 +1006,33 @@ func TestIssue12594(t *testing.T) { + } + } + ++func TestWriteLongHeader(t *testing.T) { ++ for _, test := range []struct { ++ name string ++ h *Header ++ }{{ ++ name: "name too long", ++ h: &Header{Name: strings.Repeat("a", maxSpecialFileSize)}, ++ }, { ++ name: "linkname too long", ++ h: &Header{Linkname: strings.Repeat("a", maxSpecialFileSize)}, ++ }, { ++ name: "uname too long", ++ h: &Header{Uname: strings.Repeat("a", maxSpecialFileSize)}, ++ }, { ++ name: "gname too long", ++ h: &Header{Gname: strings.Repeat("a", maxSpecialFileSize)}, ++ }, { ++ name: "PAX header too long", ++ h: &Header{PAXRecords: map[string]string{"GOLANG.x": strings.Repeat("a", maxSpecialFileSize)}}, ++ }} { ++ w := NewWriter(io.Discard) ++ if err := w.WriteHeader(test.h); err != ErrFieldTooLong { ++ t.Errorf("%v: w.WriteHeader() = %v, want ErrFieldTooLong", test.name, err) ++ } ++ } ++} ++ + // testNonEmptyWriter wraps an io.Writer and ensures that + // Write is never called with an empty buffer. + type testNonEmptyWriter struct{ io.Writer } +-- +2.33.0 + diff --git a/0023-syscall-os-exec-reject-environment-variables-contain.patch b/0023-syscall-os-exec-reject-environment-variables-contain.patch new file mode 100644 index 0000000000000000000000000000000000000000..50c3d7566db0ccfd43deb45c407a21c9ac98bb4c --- /dev/null +++ b/0023-syscall-os-exec-reject-environment-variables-contain.patch @@ -0,0 +1,248 @@ +From 0c539fa7a4a9d29252523e41e073198195ba6691 Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Mon, 17 Oct 2022 17:38:29 -0700 +Subject: [PATCH] syscall, os/exec: reject environment variables containing + NULs + +Check for and reject environment variables containing NULs. + +The conventions for passing environment variables to subprocesses +cause most or all systems to interpret a NUL as a separator. The +syscall package rejects environment variables containing a NUL +on most systems, but erroniously did not do so on Windows. This +causes an environment variable such as "FOO=a\x00BAR=b" to be +interpreted as "FOO=a", "BAR=b". + +Check for and reject NULs in environment variables passed to +syscall.StartProcess on Windows. + +Add a redundant check to os/exec as extra insurance. + +Fixes #56284 +Fixes CVE-2022-41716 + +Change-Id: I2950e2b0cb14ebd26e5629be1521858f66a7d4ae +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1609434 +Run-TryBot: Damien Neil +Reviewed-by: Tatiana Bradley +Reviewed-by: Roland Shoemaker +TryBot-Result: Security TryBots +Reviewed-on: https://go-review.googlesource.com/c/go/+/446916 +Reviewed-by: Tatiana Bradley +TryBot-Result: Gopher Robot +Run-TryBot: Matthew Dempsky +Reviewed-by: Heschi Kreinick + +Reference: https://go-review.googlesource.com/c/go/+/446916 +Conflict: src/os/exec/exec.go;src/syscall/exec_windows.go +--- + src/os/exec/env_test.go | 19 +++++++++++++------ + src/os/exec/exec.go | 38 ++++++++++++++++++++++++++++++++----- + src/os/exec/exec_test.go | 9 +++++++++ + src/syscall/exec_windows.go | 20 ++++++++++++++----- + 4 files changed, 70 insertions(+), 16 deletions(-) + +diff --git a/src/os/exec/env_test.go b/src/os/exec/env_test.go +index b5ac398..47b7c04 100644 +--- a/src/os/exec/env_test.go ++++ b/src/os/exec/env_test.go +@@ -11,9 +11,10 @@ import ( + + func TestDedupEnv(t *testing.T) { + tests := []struct { +- noCase bool +- in []string +- want []string ++ noCase bool ++ in []string ++ want []string ++ wantErr bool + }{ + { + noCase: true, +@@ -29,11 +30,17 @@ func TestDedupEnv(t *testing.T) { + in: []string{"=a", "=b", "foo", "bar"}, + want: []string{"=b", "foo", "bar"}, + }, ++ { ++ // Filter out entries containing NULs. ++ in: []string{"A=a\x00b", "B=b", "C\x00C=c"}, ++ want: []string{"B=b"}, ++ wantErr: true, ++ }, + } + for _, tt := range tests { +- got := dedupEnvCase(tt.noCase, tt.in) +- if !reflect.DeepEqual(got, tt.want) { +- t.Errorf("Dedup(%v, %q) = %q; want %q", tt.noCase, tt.in, got, tt.want) ++ got, err := dedupEnvCase(tt.noCase, tt.in) ++ if !reflect.DeepEqual(got, tt.want) || (err != nil) != tt.wantErr { ++ t.Errorf("Dedup(%v, %q) = %q, %v; want %q, error:%v", tt.noCase, tt.in, got, err, tt.want, tt.wantErr) + } + } + } +diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go +index 0c49575..6f5c61b 100644 +--- a/src/os/exec/exec.go ++++ b/src/os/exec/exec.go +@@ -414,7 +414,7 @@ func (c *Cmd) Start() error { + } + c.childFiles = append(c.childFiles, c.ExtraFiles...) + +- envv, err := c.envv() ++ env, err := c.environ() + if err != nil { + return err + } +@@ -422,7 +422,7 @@ func (c *Cmd) Start() error { + c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{ + Dir: c.Dir, + Files: c.childFiles, +- Env: addCriticalEnv(dedupEnv(envv)), ++ Env: env, + Sys: c.SysProcAttr, + }) + if err != nil { +@@ -738,16 +738,21 @@ func minInt(a, b int) int { + // dedupEnv returns a copy of env with any duplicates removed, in favor of + // later values. + // Items not of the normal environment "key=value" form are preserved unchanged. +-func dedupEnv(env []string) []string { ++func dedupEnv(env []string) ([]string, error) { + return dedupEnvCase(runtime.GOOS == "windows", env) + } + + // dedupEnvCase is dedupEnv with a case option for testing. + // If caseInsensitive is true, the case of keys is ignored. +-func dedupEnvCase(caseInsensitive bool, env []string) []string { ++func dedupEnvCase(caseInsensitive bool, env []string) ([]string, error) { ++ var err error + out := make([]string, 0, len(env)) + saw := make(map[string]int, len(env)) // key => index into out + for _, kv := range env { ++ if strings.IndexByte(kv, 0) != -1 { ++ err = errors.New("exec: environment variable contains NUL") ++ continue ++ } + eq := strings.Index(kv, "=") + if eq < 0 { + out = append(out, kv) +@@ -764,7 +769,7 @@ func dedupEnvCase(caseInsensitive bool, env []string) []string { + saw[k] = len(out) + out = append(out, kv) + } +- return out ++ return out, err + } + + // addCriticalEnv adds any critical environment variables that are required +@@ -787,3 +792,26 @@ func addCriticalEnv(env []string) []string { + } + return append(env, "SYSTEMROOT="+os.Getenv("SYSTEMROOT")) + } ++ ++// environ returns a best-effort copy of the environment in which the command ++// would be run as it is currently configured. If an error occurs in computing ++// the environment, it is returned alongside the best-effort copy. ++func (c *Cmd) environ() ([]string, error) { ++ env, err := c.envv() ++ if err != nil { ++ return env, err ++ } ++ env, dedupErr := dedupEnv(env) ++ if err == nil { ++ err = dedupErr ++ } ++ return addCriticalEnv(env), err ++} ++ ++// Environ returns a copy of the environment in which the command would be run ++// as it is currently configured. ++func (c *Cmd) Environ() []string { ++ // Intentionally ignore errors: environ returns a best-effort environment no matter what. ++ env, _ := c.environ() ++ return env ++} +diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go +index d854e0d..d03eab2 100644 +--- a/src/os/exec/exec_test.go ++++ b/src/os/exec/exec_test.go +@@ -1104,6 +1104,15 @@ func TestDedupEnvEcho(t *testing.T) { + } + } + ++func TestEnvNULCharacter(t *testing.T) { ++ cmd := helperCommand(t, "echoenv", "FOO", "BAR") ++ cmd.Env = append(cmd.Environ(), "FOO=foo\x00BAR=bar") ++ out, err := cmd.CombinedOutput() ++ if err == nil { ++ t.Errorf("output = %q; want error", string(out)) ++ } ++} ++ + func TestString(t *testing.T) { + echoPath, err := exec.LookPath("echo") + if err != nil { +diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go +index 9d10d6a..50892be 100644 +--- a/src/syscall/exec_windows.go ++++ b/src/syscall/exec_windows.go +@@ -7,6 +7,7 @@ + package syscall + + import ( ++ "internal/bytealg" + "runtime" + "sync" + "unicode/utf16" +@@ -115,12 +116,16 @@ func makeCmdLine(args []string) string { + // the representation required by CreateProcess: a sequence of NUL + // terminated strings followed by a nil. + // Last bytes are two UCS-2 NULs, or four NUL bytes. +-func createEnvBlock(envv []string) *uint16 { ++// If any string contains a NUL, it returns (nil, EINVAL). ++func createEnvBlock(envv []string) (*uint16, error) { + if len(envv) == 0 { +- return &utf16.Encode([]rune("\x00\x00"))[0] ++ return &utf16.Encode([]rune("\x00\x00"))[0], nil + } + length := 0 + for _, s := range envv { ++ if bytealg.IndexByteString(s, 0) != -1 { ++ return nil, EINVAL ++ } + length += len(s) + 1 + } + length += 1 +@@ -135,7 +140,7 @@ func createEnvBlock(envv []string) *uint16 { + } + copy(b[i:i+1], []byte{0}) + +- return &utf16.Encode([]rune(string(b)))[0] ++ return &utf16.Encode([]rune(string(b)))[0], nil + } + + func CloseOnExec(fd Handle) { +@@ -400,12 +405,17 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle + } + } + ++ envBlock, err := createEnvBlock(attr.Env) ++ if err != nil { ++ return 0, 0, err ++ } ++ + pi := new(ProcessInformation) + flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT + if sys.Token != 0 { +- err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) ++ err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, envBlock, dirp, &si.StartupInfo, pi) + } else { +- err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi) ++ err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, envBlock, dirp, &si.StartupInfo, pi) + } + if err != nil { + return 0, 0, err +-- +2.33.0 + diff --git a/0024-release-branch.go1.18-add-definition-byte-string-cut.patch b/0024-release-branch.go1.18-add-definition-byte-string-cut.patch new file mode 100644 index 0000000000000000000000000000000000000000..7f2be9c2404a51742b917e8a5bc48cd9c29fcb19 --- /dev/null +++ b/0024-release-branch.go1.18-add-definition-byte-string-cut.patch @@ -0,0 +1,430 @@ +From 2a7b541156a736984296282b816beac3dead4e8e Mon Sep 17 00:00:00 2001 +From: root +Date: Fri, 16 Dec 2022 18:14:16 +0800 +Subject: [PATCH] xxx + +Conflict: NA +Reference:https://github.com/golang/go/commit/8e36ab055162efa6f67f3b9ee62f625ac8874901 + +--- + src/bytes/bytes.go | 14 ++++ + src/bytes/bytes_test.go | 23 ++++++ + src/bytes/example_test.go | 139 ++++++++++++++++++------------------ + src/strings/example_test.go | 58 +++++++++------ + src/strings/strings.go | 11 +++ + src/strings/strings_test.go | 25 ++++++- + 6 files changed, 179 insertions(+), 91 deletions(-) + +diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go +index ce52649..50b43a4 100644 +--- a/src/bytes/bytes.go ++++ b/src/bytes/bytes.go +@@ -1174,3 +1174,17 @@ func Index(s, sep []byte) int { + } + return -1 + } ++ ++ ++// Cut slices s around the first instance of sep, ++// returning the text before and after sep. ++// The found result reports whether sep appears in s. ++// If sep does not appear in s, cut returns s, "", false. ++// ++// Cut returns slices of the original slice s, not copies. ++func Cut(s, sep []byte) (before, after []byte, found bool) { ++ if i := Index(s, sep); i >= 0 { ++ return s[:i], s[i+len(sep):], true ++ } ++ return s, nil, false ++} +diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go +index 544ee46..538e613 100644 +--- a/src/bytes/bytes_test.go ++++ b/src/bytes/bytes_test.go +@@ -1565,6 +1565,29 @@ func TestEqualFold(t *testing.T) { + } + } + ++var cutTests = []struct { ++ s, sep string ++ before, after string ++ found bool ++}{ ++ {"abc", "b", "a", "c", true}, ++ {"abc", "a", "", "bc", true}, ++ {"abc", "c", "ab", "", true}, ++ {"abc", "abc", "", "", true}, ++ {"abc", "", "", "abc", true}, ++ {"abc", "d", "abc", "", false}, ++ {"", "d", "", "", false}, ++ {"", "", "", "", true}, ++} ++ ++func TestCut(t *testing.T) { ++ for _, tt := range cutTests { ++ if before, after, found := Cut([]byte(tt.s), []byte(tt.sep)); string(before) != tt.before || string(after) != tt.after || found != tt.found { ++ t.Errorf("Cut(%q, %q) = %q, %q, %v, want %q, %q, %v", tt.s, tt.sep, before, after, found, tt.before, tt.after, tt.found) ++ } ++ } ++} ++ + func TestBufferGrowNegative(t *testing.T) { + defer func() { + if err := recover(); err == nil { +diff --git a/src/bytes/example_test.go b/src/bytes/example_test.go +index ae93202..82de99d 100644 +--- a/src/bytes/example_test.go ++++ b/src/bytes/example_test.go +@@ -92,36 +92,6 @@ func ExampleCompare_search() { + } + } + +-func ExampleTrimSuffix() { +- var b = []byte("Hello, goodbye, etc!") +- b = bytes.TrimSuffix(b, []byte("goodbye, etc!")) +- b = bytes.TrimSuffix(b, []byte("gopher")) +- b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...) +- os.Stdout.Write(b) +- // Output: Hello, world! +-} +- +-func ExampleTrimPrefix() { +- var b = []byte("Goodbye,, world!") +- b = bytes.TrimPrefix(b, []byte("Goodbye,")) +- b = bytes.TrimPrefix(b, []byte("See ya,")) +- fmt.Printf("Hello%s", b) +- // Output: Hello, world! +-} +- +-func ExampleFields() { +- fmt.Printf("Fields are: %q", bytes.Fields([]byte(" foo bar baz "))) +- // Output: Fields are: ["foo" "bar" "baz"] +-} +- +-func ExampleFieldsFunc() { +- f := func(c rune) bool { +- return !unicode.IsLetter(c) && !unicode.IsNumber(c) +- } +- fmt.Printf("Fields are: %q", bytes.FieldsFunc([]byte(" foo1;bar2,baz3..."), f)) +- // Output: Fields are: ["foo1" "bar2" "baz3"] +-} +- + func ExampleContains() { + fmt.Println(bytes.Contains([]byte("seafood"), []byte("foo"))) + fmt.Println(bytes.Contains([]byte("seafood"), []byte("bar"))) +@@ -168,6 +138,22 @@ func ExampleCount() { + // 5 + } + ++func ExampleCut() { ++ show := func(s, sep string) { ++ before, after, found := bytes.Cut([]byte(s), []byte(sep)) ++ fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found) ++ } ++ show("Gopher", "Go") ++ show("Gopher", "ph") ++ show("Gopher", "er") ++ show("Gopher", "Badger") ++ // Output: ++ // Cut("Gopher", "Go") = "", "pher", true ++ // Cut("Gopher", "ph") = "Go", "er", true ++ // Cut("Gopher", "er") = "Goph", "", true ++ // Cut("Gopher", "Badger") = "Gopher", "", false ++} ++ + func ExampleEqual() { + fmt.Println(bytes.Equal([]byte("Go"), []byte("Go"))) + fmt.Println(bytes.Equal([]byte("Go"), []byte("C++"))) +@@ -181,6 +167,19 @@ func ExampleEqualFold() { + // Output: true + } + ++func ExampleFields() { ++ fmt.Printf("Fields are: %q", bytes.Fields([]byte(" foo bar baz "))) ++ // Output: Fields are: ["foo" "bar" "baz"] ++} ++ ++func ExampleFieldsFunc() { ++ f := func(c rune) bool { ++ return !unicode.IsLetter(c) && !unicode.IsNumber(c) ++ } ++ fmt.Printf("Fields are: %q", bytes.FieldsFunc([]byte(" foo1;bar2,baz3..."), f)) ++ // Output: Fields are: ["foo1" "bar2" "baz3"] ++} ++ + func ExampleHasPrefix() { + fmt.Println(bytes.HasPrefix([]byte("Gopher"), []byte("Go"))) + fmt.Println(bytes.HasPrefix([]byte("Gopher"), []byte("C"))) +@@ -246,6 +245,12 @@ func ExampleIndexRune() { + // -1 + } + ++func ExampleJoin() { ++ s := [][]byte{[]byte("foo"), []byte("bar"), []byte("baz")} ++ fmt.Printf("%s", bytes.Join(s, []byte(", "))) ++ // Output: foo, bar, baz ++} ++ + func ExampleLastIndex() { + fmt.Println(bytes.Index([]byte("go gopher"), []byte("go"))) + fmt.Println(bytes.LastIndex([]byte("go gopher"), []byte("go"))) +@@ -286,10 +291,12 @@ func ExampleLastIndexFunc() { + // -1 + } + +-func ExampleJoin() { +- s := [][]byte{[]byte("foo"), []byte("bar"), []byte("baz")} +- fmt.Printf("%s", bytes.Join(s, []byte(", "))) +- // Output: foo, bar, baz ++func ExampleReader_Len() { ++ fmt.Println(bytes.NewReader([]byte("Hi!")).Len()) ++ fmt.Println(bytes.NewReader([]byte("こんにちは!")).Len()) ++ // Output: ++ // 3 ++ // 16 + } + + func ExampleRepeat() { +@@ -399,20 +406,6 @@ func ExampleTrimFunc() { + // go-gopher! + } + +-func ExampleMap() { +- rot13 := func(r rune) rune { +- switch { +- case r >= 'A' && r <= 'Z': +- return 'A' + (r-'A'+13)%26 +- case r >= 'a' && r <= 'z': +- return 'a' + (r-'a'+13)%26 +- } +- return r +- } +- fmt.Printf("%s", bytes.Map(rot13, []byte("'Twas brillig and the slithy gopher..."))) +- // Output: 'Gjnf oevyyvt naq gur fyvgul tbcure... +-} +- + func ExampleTrimLeft() { + fmt.Print(string(bytes.TrimLeft([]byte("453gopher8257"), "0123456789"))) + // Output: +@@ -429,11 +422,28 @@ func ExampleTrimLeftFunc() { + // go-gopher!567 + } + ++func ExampleTrimPrefix() { ++ var b = []byte("Goodbye,, world!") ++ b = bytes.TrimPrefix(b, []byte("Goodbye,")) ++ b = bytes.TrimPrefix(b, []byte("See ya,")) ++ fmt.Printf("Hello%s", b) ++ // Output: Hello, world! ++} ++ + func ExampleTrimSpace() { + fmt.Printf("%s", bytes.TrimSpace([]byte(" \t\n a lone gopher \n\t\r\n"))) + // Output: a lone gopher + } + ++func ExampleTrimSuffix() { ++ var b = []byte("Hello, goodbye, etc!") ++ b = bytes.TrimSuffix(b, []byte("goodbye, etc!")) ++ b = bytes.TrimSuffix(b, []byte("gopher")) ++ b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...) ++ os.Stdout.Write(b) ++ // Output: Hello, world! ++} ++ + func ExampleTrimRight() { + fmt.Print(string(bytes.TrimRight([]byte("453gopher8257"), "0123456789"))) + // Output: +@@ -450,21 +460,6 @@ func ExampleTrimRightFunc() { + // 1234go-gopher! + } + +-func ExampleToUpper() { +- fmt.Printf("%s", bytes.ToUpper([]byte("Gopher"))) +- // Output: GOPHER +-} +- +-func ExampleToUpperSpecial() { +- str := []byte("ahoj vývojári golang") +- totitle := bytes.ToUpperSpecial(unicode.AzeriCase, str) +- fmt.Println("Original : " + string(str)) +- fmt.Println("ToUpper : " + string(totitle)) +- // Output: +- // Original : ahoj vývojári golang +- // ToUpper : AHOJ VÝVOJÁRİ GOLANG +-} +- + func ExampleToLower() { + fmt.Printf("%s", bytes.ToLower([]byte("Gopher"))) + // Output: gopher +@@ -480,10 +475,16 @@ func ExampleToLowerSpecial() { + // ToLower : ahoj vývojári golang + } + +-func ExampleReader_Len() { +- fmt.Println(bytes.NewReader([]byte("Hi!")).Len()) +- fmt.Println(bytes.NewReader([]byte("こんにちは!")).Len()) +- // Output: +- // 3 +- // 16 ++func ExampleToUpper() { ++ fmt.Printf("%s", bytes.ToUpper([]byte("Gopher"))) ++ // Output: GOPHER ++} ++ ++func ExampleToUpperSpecial() { ++ str := []byte("ahoj vyvojári golang") ++ totitle := bytes.ToUpperSpecial(unicode.AzeriCase, str) ++ fmt.Println("Original : " + string(str)) ++ fmt.Println("ToUpper : " + string(totitle)) ++ // Original : ahoj vyvojári golang ++ // ToUpper : AHOJ VYVOJáR? GOLANG + } +diff --git a/src/strings/example_test.go b/src/strings/example_test.go +index 375f9ca..b75424a 100644 +--- a/src/strings/example_test.go ++++ b/src/strings/example_test.go +@@ -9,18 +9,15 @@ import ( + "strings" + "unicode" + ) +- +-func ExampleFields() { +- fmt.Printf("Fields are: %q", strings.Fields(" foo bar baz ")) +- // Output: Fields are: ["foo" "bar" "baz"] +-} +- +-func ExampleFieldsFunc() { +- f := func(c rune) bool { +- return !unicode.IsLetter(c) && !unicode.IsNumber(c) ++func ExampleBuilder() { ++ var b strings.Builder ++ for i := 3; i >= 1; i-- { ++ fmt.Fprintf(&b, "%d...", i) + } +- fmt.Printf("Fields are: %q", strings.FieldsFunc(" foo1;bar2,baz3...", f)) +- // Output: Fields are: ["foo1" "bar2" "baz3"] ++ b.WriteString("ignition") ++ fmt.Println(b.String()) ++ ++ // Output: 3...2...1...ignition + } + + func ExampleCompare() { +@@ -79,11 +76,40 @@ func ExampleCount() { + // 5 + } + ++func ExampleCut() { ++ show := func(s, sep string) { ++ before, after, found := strings.Cut(s, sep) ++ fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found) ++ } ++ show("Gopher", "Go") ++ show("Gopher", "ph") ++ show("Gopher", "er") ++ show("Gopher", "Badger") ++ // Output: ++ // Cut("Gopher", "Go") = "", "pher", true ++ // Cut("Gopher", "ph") = "Go", "er", true ++ // Cut("Gopher", "er") = "Goph", "", true ++ // Cut("Gopher", "Badger") = "Gopher", "", false ++} ++ + func ExampleEqualFold() { + fmt.Println(strings.EqualFold("Go", "go")) + // Output: true + } + ++func ExampleFields() { ++ fmt.Printf("Fields are: %q", strings.Fields(" foo bar baz ")) ++ // Output: Fields are: ["foo" "bar" "baz"] ++} ++ ++func ExampleFieldsFunc() { ++ f := func(c rune) bool { ++ return !unicode.IsLetter(c) && !unicode.IsNumber(c) ++ } ++ fmt.Printf("Fields are: %q", strings.FieldsFunc(" foo1;bar2,baz3...", f)) ++ // Output: Fields are: ["foo1" "bar2" "baz3"] ++} ++ + func ExampleHasPrefix() { + fmt.Println(strings.HasPrefix("Gopher", "Go")) + fmt.Println(strings.HasPrefix("Gopher", "C")) +@@ -370,14 +396,3 @@ func ExampleTrimRightFunc() { + })) + // Output: ¡¡¡Hello, Gophers + } +- +-func ExampleBuilder() { +- var b strings.Builder +- for i := 3; i >= 1; i-- { +- fmt.Fprintf(&b, "%d...", i) +- } +- b.WriteString("ignition") +- fmt.Println(b.String()) +- +- // Output: 3...2...1...ignition +-} +diff --git a/src/strings/strings.go b/src/strings/strings.go +index b429735..0c94395 100644 +--- a/src/strings/strings.go ++++ b/src/strings/strings.go +@@ -1100,3 +1100,14 @@ func Index(s, substr string) int { + } + return -1 + } ++ ++// Cut slices s around the first instance of sep, ++// returning the text before and after sep. ++// The found result reports whether sep appears in s. ++// If sep does not appear in s, cut returns s, "", false. ++func Cut(s, sep string) (before, after string, found bool) { ++ if i := Index(s, sep); i >= 0 { ++ return s[:i], s[i+len(sep):], true ++ } ++ return s, "", false ++} +diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go +index 09e5b27..1ebce42 100644 +--- a/src/strings/strings_test.go ++++ b/src/strings/strings_test.go +@@ -1577,11 +1577,34 @@ var CountTests = []struct { + func TestCount(t *testing.T) { + for _, tt := range CountTests { + if num := Count(tt.s, tt.sep); num != tt.num { +- t.Errorf("Count(\"%s\", \"%s\") = %d, want %d", tt.s, tt.sep, num, tt.num) ++ t.Errorf("Count(%q, %q) = %d, want %d", tt.s, tt.sep, num, tt.num) + } + } + } + ++var cutTests = []struct { ++ s, sep string ++ before, after string ++ found bool ++}{ ++ {"abc", "b", "a", "c", true}, ++ {"abc", "a", "", "bc", true}, ++ {"abc", "c", "ab", "", true}, ++ {"abc", "abc", "", "", true}, ++ {"abc", "", "", "abc", true}, ++ {"abc", "d", "abc", "", false}, ++ {"", "d", "", "", false}, ++ {"", "", "", "", true}, ++} ++ ++func TestCut(t *testing.T) { ++ for _, tt := range cutTests { ++ if before, after, found := Cut(tt.s, tt.sep); before != tt.before || after != tt.after || found != tt.found { ++ t.Errorf("Cut(%q, %q) = %q, %q, %v, want %q, %q, %v", tt.s, tt.sep, before, after, found, tt.before, tt.after, tt.found) ++ } ++ } ++} ++ + func makeBenchInputHard() string { + tokens := [...]string{ + "", "

", "", "", +-- +2.27.0 diff --git a/backport-0013-release-branch.go1.13-security-src-go.mod-import-x-c.patch b/backport-0013-release-branch.go1.13-security-src-go.mod-import-x-c.patch deleted file mode 100644 index 5a6166b548173a555a66912ceedfca041d44bedc..0000000000000000000000000000000000000000 --- a/backport-0013-release-branch.go1.13-security-src-go.mod-import-x-c.patch +++ /dev/null @@ -1,124 +0,0 @@ -From f938e06d0623d0e1de202575d16f1e126741f6e0 Mon Sep 17 00:00:00 2001 -From: Filippo Valsorda -Date: Fri, 24 Jan 2020 18:04:20 -0500 -Subject: [PATCH] [release-branch.go1.13-security] src/go.mod: import - x/crypto/cryptobyte security fix for 32-bit archs - - cryptobyte: fix panic due to malformed ASN.1 inputs on 32-bit archs - - When int is 32 bits wide (on 32-bit architectures like 386 and arm), an - overflow could occur, causing a panic, due to malformed ASN.1 being - passed to any of the ASN1 methods of String. - - Tested on linux/386 and darwin/amd64. - - This fixes CVE-2020-7919 and was found thanks to the Project Wycheproof - test vectors. - - Change-Id: I8c9696a8bfad1b40ec877cd740dba3467d66ab54 - Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/645211 - Reviewed-by: Katie Hockman - Reviewed-by: Adam Langley - -x/crypto/cryptobyte is used in crypto/x509 for parsing certificates. -Malformed certificates might cause a panic during parsing on 32-bit -architectures (like arm and 386). - -Change-Id: I840feb54eba880dbb96780ef7adcade073c4c4e3 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/647741 -Reviewed-by: Katie Hockman ---- - src/go.mod | 2 +- - src/go.sum | 4 ++-- - src/vendor/golang.org/x/crypto/cryptobyte/asn1.go | 5 +++-- - src/vendor/golang.org/x/crypto/cryptobyte/string.go | 7 +------ - src/vendor/modules.txt | 2 +- - 5 files changed, 8 insertions(+), 12 deletions(-) - -diff --git a/src/go.mod b/src/go.mod -index 90af2a7ea0..9c9026f0d8 100644 ---- a/src/go.mod -+++ b/src/go.mod -@@ -3,7 +3,7 @@ module std - go 1.12 - - require ( -- golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 -+ golang.org/x/crypto v0.0.0-20200124225646-8b5121be2f68 - golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 - golang.org/x/sys v0.0.0-20190529130038-5219a1e1c5f8 // indirect - golang.org/x/text v0.3.2 // indirect -diff --git a/src/go.sum b/src/go.sum -index e358118e4c..e408f66328 100644 ---- a/src/go.sum -+++ b/src/go.sum -@@ -1,6 +1,6 @@ - golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= --golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= --golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -+golang.org/x/crypto v0.0.0-20200124225646-8b5121be2f68 h1:WPLCzSEbawp58wezcvLvLnvhiDJAai54ESbc41NdXS0= -+golang.org/x/crypto v0.0.0-20200124225646-8b5121be2f68/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= - golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= - golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= - golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -diff --git a/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go b/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go -index 528b9bff67..f930f7e526 100644 ---- a/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go -+++ b/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go -@@ -470,7 +470,8 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool { - // It reports whether the read was successful. - func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool { - var bytes String -- if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 { -+ if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 || -+ len(bytes)*8/8 != len(bytes) { - return false - } - -@@ -740,7 +741,7 @@ func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool { - length = headerLen + len32 - } - -- if uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) { -+ if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) { - return false - } - if skipHeader && !out.Skip(int(headerLen)) { -diff --git a/src/vendor/golang.org/x/crypto/cryptobyte/string.go b/src/vendor/golang.org/x/crypto/cryptobyte/string.go -index 39bf98aeea..589d297e6b 100644 ---- a/src/vendor/golang.org/x/crypto/cryptobyte/string.go -+++ b/src/vendor/golang.org/x/crypto/cryptobyte/string.go -@@ -24,7 +24,7 @@ type String []byte - // read advances a String by n bytes and returns them. If less than n bytes - // remain, it returns nil. - func (s *String) read(n int) []byte { -- if len(*s) < n { -+ if len(*s) < n || n < 0 { - return nil - } - v := (*s)[:n] -@@ -105,11 +105,6 @@ func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool { - length = length << 8 - length = length | uint32(b) - } -- if int(length) < 0 { -- // This currently cannot overflow because we read uint24 at most, but check -- // anyway in case that changes in the future. -- return false -- } - v := s.read(int(length)) - if v == nil { - return false -diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt -index 453a312661..cff8acd02e 100644 ---- a/src/vendor/modules.txt -+++ b/src/vendor/modules.txt -@@ -1,4 +1,4 @@ --# golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 -+# golang.org/x/crypto v0.0.0-20200124225646-8b5121be2f68 - golang.org/x/crypto/chacha20poly1305 - golang.org/x/crypto/cryptobyte - golang.org/x/crypto/cryptobyte/asn1 --- -2.17.1 - diff --git a/go1.13.3.src.tar.gz b/go1.17.3.src.tar.gz similarity index 68% rename from go1.13.3.src.tar.gz rename to go1.17.3.src.tar.gz index c3aadce8927e5ac1168fbb816e9d5bfec3be4e2a..44c4f49fb37bd15237686ef83e5a0741e0e406df 100644 Binary files a/go1.13.3.src.tar.gz and b/go1.17.3.src.tar.gz differ diff --git a/golang.spec b/golang.spec index 2cddb145e3ece4e722ad1837df5810491733e24b..5de473a9ca164daba52a28303abaffbb84a42224 100644 --- a/golang.spec +++ b/golang.spec @@ -2,28 +2,29 @@ %global _binaries_in_noarch_packages_terminate_build 0 %global golibdir %{_libdir}/golang %global goroot /usr/lib/%{name} -%global go_api 1.13 -%global go_version 1.13 +%global go_api 1.17 +%global go_version 1.17 %global __spec_install_post /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot /usr/lib/rpm/brp-compress %global __requires_exclude_from ^(%{_datadir}|/usr/lib)/%{name}/(doc|src)/.*$ %global __strip /bin/true +%global vendor %{?_vendor:%{_vendor}}%{!?_vendor:openEuler} %define _use_internal_dependency_generator 0 %define __find_requires %{nil} %bcond_with bootstrap -%ifarch x86_64 aarch64 +%ifarch x86_64 aarch64 riscv64 %bcond_without ignore_tests %else %bcond_with ignore_tests %endif -%ifarch x86_64 aarch64 +%ifarch x86_64 aarch64 riscv64 %global external_linker 1 %else %global external_linker 0 %endif -%ifarch x86_64 aarch64 +%ifarch x86_64 aarch64 riscv64 %global cgo_enabled 1 %else %global cgo_enabled 0 @@ -41,11 +42,7 @@ %global fail_on_tests 1 %endif -%ifarch x86_64 aarch64 -%global shared 1 -%else %global shared 0 -%endif %ifarch x86_64 %global race 1 @@ -59,14 +56,18 @@ %ifarch aarch64 %global gohostarch arm64 %endif +%ifarch riscv64 +%global gohostarch riscv64 +%endif + Name: golang -Version: 1.13.3 -Release: 6 +Version: 1.17.3 +Release: 13 Summary: The Go Programming Language License: BSD and Public Domain -URL: http://golang.org/ -Source0: https://dl.google.com/go/go%{version}.src.tar.gz +URL: https://golang.org/ +Source0: https://dl.google.com/go/go1.17.3.src.tar.gz %if !%{golang_bootstrap} BuildRequires: gcc-go >= 5 @@ -91,7 +92,7 @@ Obsoletes: %{name}-cover < 0-12.1 Requires(post): %{_sbindir}/update-alternatives Requires(postun): %{_sbindir}/update-alternatives -Requires: glibc gcc git subversion +Recommends: glibc gcc git subversion # generated by: @@ -147,25 +148,35 @@ Obsoletes: %{name}-docs Obsoletes: %{name}-data < 1.1.1-4 Obsoletes: %{name}-vim < 1.4 Obsoletes: emacs-%{name} < 1.4 -Requires: openEuler-rpm-config - -Patch6002: 0002-syscall-expose-IfInfomsg.X__ifi_pad-on-s390x.patch -Patch6003: 0003-golang-delete-pem-files.patch -Patch6004: 0004-syscall-implement-rawVforkSyscall-for-linux-arm64.patch -Patch6005: 0005-runtime-fix-crash-during-VDSO-calls-on-arm.patch -Patch6006: 0006-runtime-save-fetch-g-register-during-VDSO-on-ARM-and.patch -Patch6007: 0007-runtime-don-t-fetch-G-from-signal-stack-when-using-c.patch -Patch6008: 0008-runtime-don-t-save-G-during-VDSO-if-we-re-handling-s.patch -Patch6009: 0009-release-branch.go1.13-net-http-don-t-cache-http2.err.patch -Patch6010: 0010-release-branch.go1.13-net-http-fix-Server.ConnContex.patch -Patch6011: 0011-release-branch.go1.13-runtime-fix-textOff-for-multip.patch -Patch6012: 0012-release-branch.go1.13-runtime-ensure-memmove-write-p.patch -Patch6013: backport-0013-release-branch.go1.13-security-src-go.mod-import-x-c.patch -Patch6014: 0013-drop-hard-code-cert.patch +Requires: %{vendor}-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 +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 +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 +Patch6019: 0019-release-branch.go1.18-net-http-update-bundled-golang.patch +Patch6020: 0020-release-branch.go1.18-regexp-limit-size-of-parsed-re.patch +Patch6021: 0021-release-branch.go1.18-net-http-httputil-avoid-query-.patch +Patch6022: 0022-release-branch.go1.18-archive-tar-limit-size-of-head.patch +Patch6023: 0023-syscall-os-exec-reject-environment-variables-contain.patch +Patch6024: 0024-release-branch.go1.18-add-definition-byte-string-cut.patch ExclusiveArch: %{golang_arches} - %description %{summary}. @@ -260,7 +271,7 @@ rm -rf pkg/obj/go-build/* mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{goroot} -cp -apv api bin doc favicon.ico lib pkg robots.txt src misc test VERSION \ +cp -apv api bin doc lib pkg src misc test VERSION \ %{buildroot}%{goroot} # bz1099206 @@ -356,7 +367,7 @@ export GO_TEST_TIMEOUT_SCALE=2 %if %{fail_on_tests} echo tests ignored %else -./run.bash --no-rebuild -v -v -v -k || : +./run.bash --no-rebuild -v -v -v -k go_test:testing || : %endif cd .. @@ -370,7 +381,12 @@ if [ $1 = 0 ]; then %{_sbindir}/update-alternatives --remove go %{goroot}/bin/go fi +%if %{shared} +%files -f go-pkg.list -f go-shared.list +%else %files -f go-pkg.list +%endif + %doc AUTHORS CONTRIBUTORS LICENSE PATENTS %doc %{goroot}/VERSION %dir %{goroot}/doc @@ -380,6 +396,7 @@ fi %exclude %{goroot}/doc/ %exclude %{goroot}/misc/ %exclude %{goroot}/test/ +%exclude %{goroot}/lib/ %{goroot}/* %dir %{gopath} %dir %{gopath}/src @@ -390,25 +407,84 @@ fi %dir %{gopath}/src/golang.org %dir %{gopath}/src/golang.org/x -%files help -f go-docs.list -f go-shared.list +%files help -f go-docs.list %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog -* Tue May 12 2020 lixiang - 1.13.6 -- rename tar name and make it same with upstream - -* Tue Mar 17 2020 jingrui - 1.13.5 -- drop hard code cert - -* Mon Mar 23 2020 jingrui - 1.13.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 +* Sat Dec 17 2022 wanglimin - 1.17.3-13 +- Add string cut + +* Fri Oct 11 2022 hanchao - 1.17.3-12 +- Type:CVE +- CVE:CVE-2022-41716 +- SUG:NA +- DESC: remove hard code and strong dependency of git, subversion and mercurial + +* Fri Oct 11 2022 hanchao - 1.17.3-11 +- Type:CVE +- CVE:CVE-2022-41716 +- SUG:NA +- DESC: fix CVE-2022-41716 + +* Mon Oct 10 2022 hanchao - 1.17.3-10 +- Type:CVE +- CVE:CVE-2022-41715,CVE-2022-2880,CVE-2022-2879 +- SUG:NA +- DESC: fix CVE-2022-41715,CVE-2022-2880,CVE-2022-2879 + +* Thu Sep 15 2022 hanchao - 1.17.3-9 +- Type:CVE +- CVE:CVE-2022-27664 +- SUG:NA +- DESC: fix CVE-2022-27664 + +* Thu Sep 8 2022 hanchao - 1.17.3-8 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC: golang: modify the golang.spec to remove unnecessary files + from golang-help package + +* 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 +- SUG:NA +- DESC: fix CVE-2022-32189 + +* 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 +- 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 +- 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 +- 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 diff --git a/golang.yaml b/golang.yaml new file mode 100644 index 0000000000000000000000000000000000000000..73d095a10f43977bbf4052fd1e397d8309ab3c1d --- /dev/null +++ b/golang.yaml @@ -0,0 +1,4 @@ +version_control: github +src_repo: golang/go +tag_prefix: ^go +seperator: .