!310 sync: synchronize to latest code
From: @hcnbxx Reviewed-by: @flyflyflypeng, @jing-rui Signed-off-by: @flyflyflypeng, @jing-rui
This commit is contained in:
commit
34dafd6581
@ -0,0 +1,180 @@
|
||||
From 67c5ff52473c4956893b7500656954a6d898f1ca Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Wed, 7 Jun 2023 15:27:13 -0700
|
||||
Subject: [PATCH] [Backport] crypto/tls: restrict RSA keys in certificates to
|
||||
<= 8192 bits
|
||||
|
||||
Extremely large RSA keys in certificate chains can cause a client/server
|
||||
to expend significant CPU time verifying signatures. Limit this by
|
||||
restricting the size of RSA keys transmitted during handshakes to <=
|
||||
8192 bits.
|
||||
|
||||
Based on a survey of publicly trusted RSA keys, there are currently only
|
||||
three certificates in circulation with keys larger than this, and all
|
||||
three appear to be test certificates that are not actively deployed. It
|
||||
is possible there are larger keys in use in private PKIs, but we target
|
||||
the web PKI, so causing breakage here in the interests of increasing the
|
||||
default safety of users of crypto/tls seems reasonable.
|
||||
|
||||
Thanks to Mateusz Poliwczak for reporting this issue.
|
||||
|
||||
Note: The upstream does not submit this change to go1.17 according to the rules of MinorReleases.
|
||||
Corego3.x are based on go1.17.8. Therefore, it need to submit the change to corego3.x.
|
||||
|
||||
Edited-by: machangwang m00509938
|
||||
|
||||
Updates #61460
|
||||
Fixes #61579
|
||||
Fixes CVE-2023-29409
|
||||
|
||||
Change-Id: Ie35038515a649199a36a12fc2c5df3af855dca6c
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1912161
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
(cherry picked from commit d865c715d92887361e4bd5596e19e513f27781b7)
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1965487
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/514915
|
||||
Run-TryBot: David Chase <drchase@google.com>
|
||||
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
|
||||
TryBot-Bypass: David Chase <drchase@google.com>
|
||||
Signed-off-by: Ma Chang Wang machangwang@huawei.com
|
||||
|
||||
Reference: https://go-review.googlesource.com/c/go/+/514915
|
||||
Conflict:NA
|
||||
---
|
||||
src/crypto/tls/handshake_client.go | 8 +++
|
||||
src/crypto/tls/handshake_client_test.go | 78 +++++++++++++++++++++++++
|
||||
src/crypto/tls/handshake_server.go | 4 ++
|
||||
3 files changed, 90 insertions(+)
|
||||
|
||||
diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
|
||||
index 85622f159b..828d2cb378 100644
|
||||
--- a/src/crypto/tls/handshake_client.go
|
||||
+++ b/src/crypto/tls/handshake_client.go
|
||||
@@ -852,6 +852,10 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+// maxRSAKeySize is the maximum RSA key size in bits that we are willing
|
||||
+// to verify the signatures of during a TLS handshake.
|
||||
+const maxRSAKeySize = 8192
|
||||
+
|
||||
// verifyServerCertificate parses and verifies the provided chain, setting
|
||||
// c.verifiedChains and c.peerCertificates or sending the appropriate alert.
|
||||
func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
|
||||
@@ -862,6 +866,10 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
|
||||
c.sendAlert(alertBadCertificate)
|
||||
return errors.New("tls: failed to parse certificate from server: " + err.Error())
|
||||
}
|
||||
+ if cert.PublicKeyAlgorithm == x509.RSA && cert.PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
|
||||
+ c.sendAlert(alertBadCertificate)
|
||||
+ return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
|
||||
+ }
|
||||
certs[i] = cert
|
||||
}
|
||||
|
||||
diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go
|
||||
index 0228745155..d581cb1104 100644
|
||||
--- a/src/crypto/tls/handshake_client_test.go
|
||||
+++ b/src/crypto/tls/handshake_client_test.go
|
||||
@@ -2595,3 +2595,81 @@ func TestClientHandshakeContextCancellation(t *testing.T) {
|
||||
t.Error("Client connection was not closed when the context was canceled")
|
||||
}
|
||||
}
|
||||
+
|
||||
+// discardConn wraps a net.Conn but discards all writes, but reports that they happened.
|
||||
+type discardConn struct {
|
||||
+ net.Conn
|
||||
+}
|
||||
+
|
||||
+func (dc *discardConn) Write(data []byte) (int, error) {
|
||||
+ return len(data), nil
|
||||
+}
|
||||
+
|
||||
+// largeRSAKeyCertPEM contains a 8193 bit RSA key
|
||||
+const largeRSAKeyCertPEM = `-----BEGIN CERTIFICATE-----
|
||||
+MIIInjCCBIWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0
|
||||
+aW5nMB4XDTIzMDYwNzIxMjMzNloXDTIzMDYwNzIzMjMzNlowEjEQMA4GA1UEAxMH
|
||||
+dGVzdGluZzCCBCIwDQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBAWdHsf6Rh2Ca
|
||||
+n2SQwn4t4OQrOjbLLdGE1pM6TBKKrHUFy62uEL8atNjlcfXIsa4aEu3xNGiqxqur
|
||||
+ZectlkZbm0FkaaQ1Wr9oikDY3KfjuaXdPdO/XC/h8AKNxlDOylyXwUSK/CuYb+1j
|
||||
+gy8yF5QFvVfwW/xwTlHmhUeSkVSQPosfQ6yXNNsmMzkd+ZPWLrfq4R+wiNtwYGu0
|
||||
+WSBcI/M9o8/vrNLnIppoiBJJ13j9CR1ToEAzOFh9wwRWLY10oZhoh1ONN1KQURx4
|
||||
+qedzvvP2DSjZbUccdvl2rBGvZpzfOiFdm1FCnxB0c72Cqx+GTHXBFf8bsa7KHky9
|
||||
+sNO1GUanbq17WoDNgwbY6H51bfShqv0CErxatwWox3we4EcAmFHPVTCYL1oWVMGo
|
||||
+a3Eth91NZj+b/nGhF9lhHKGzXSv9brmLLkfvM1jA6XhNhA7BQ5Vz67lj2j3XfXdh
|
||||
+t/BU5pBXbL4Ut4mIhT1YnKXAjX2/LF5RHQTE8Vwkx5JAEKZyUEGOReD/B+7GOrLp
|
||||
+HduMT9vZAc5aR2k9I8qq1zBAzsL69lyQNAPaDYd1BIAjUety9gAYaSQffCgAgpRO
|
||||
+Gt+DYvxS+7AT/yEd5h74MU2AH7KrAkbXOtlwupiGwhMVTstncDJWXMJqbBhyHPF8
|
||||
+3UmZH0hbL4PYmzSj9LDWQQXI2tv6vrCpfts3Cqhqxz9vRpgY7t1Wu6l/r+KxYYz3
|
||||
+1pcGpPvRmPh0DJm7cPTiXqPnZcPt+ulSaSdlxmd19OnvG5awp0fXhxryZVwuiT8G
|
||||
+VDkhyARrxYrdjlINsZJZbQjO0t8ketXAELJOnbFXXzeCOosyOHkLwsqOO96AVJA8
|
||||
+45ZVL5m95ClGy0RSrjVIkXsxTAMVG6SPAqKwk6vmTdRGuSPS4rhgckPVDHmccmuq
|
||||
+dfnT2YkX+wB2/M3oCgU+s30fAHGkbGZ0pCdNbFYFZLiH0iiMbTDl/0L/z7IdK0nH
|
||||
+GLHVE7apPraKC6xl6rPWsD2iSfrmtIPQa0+rqbIVvKP5JdfJ8J4alI+OxFw/znQe
|
||||
+V0/Rez0j22Fe119LZFFSXhRv+ZSvcq20xDwh00mzcumPWpYuCVPozA18yIhC9tNn
|
||||
+ALHndz0tDseIdy9vC71jQWy9iwri3ueN0DekMMF8JGzI1Z6BAFzgyAx3DkHtwHg7
|
||||
+B7qD0jPG5hJ5+yt323fYgJsuEAYoZ8/jzZ01pkX8bt+UsVN0DGnSGsI2ktnIIk3J
|
||||
+l+8krjmUy6EaW79nITwoOqaeHOIp8m3UkjEcoKOYrzHRKqRy+A09rY+m/cAQaafW
|
||||
+4xp0Zv7qZPLwnu0jsqB4jD8Ll9yPB02ndsoV6U5PeHzTkVhPml19jKUAwFfs7TJg
|
||||
+kXy+/xFhYVUCAwEAATANBgkqhkiG9w0BAQsFAAOCBAIAAQnZY77pMNeypfpba2WK
|
||||
+aDasT7dk2JqP0eukJCVPTN24Zca+xJNPdzuBATm/8SdZK9lddIbjSnWRsKvTnO2r
|
||||
+/rYdlPf3jM5uuJtb8+Uwwe1s+gszelGS9G/lzzq+ehWicRIq2PFcs8o3iQMfENiv
|
||||
+qILJ+xjcrvms5ZPDNahWkfRx3KCg8Q+/at2n5p7XYjMPYiLKHnDC+RE2b1qT20IZ
|
||||
+FhuK/fTWLmKbfYFNNga6GC4qcaZJ7x0pbm4SDTYp0tkhzcHzwKhidfNB5J2vNz6l
|
||||
+Ur6wiYwamFTLqcOwWo7rdvI+sSn05WQBv0QZlzFX+OAu0l7WQ7yU+noOxBhjvHds
|
||||
+14+r9qcQZg2q9kG+evopYZqYXRUNNlZKo9MRBXhfrISulFAc5lRFQIXMXnglvAu+
|
||||
+Ipz2gomEAOcOPNNVldhKAU94GAMJd/KfN0ZP7gX3YvPzuYU6XDhag5RTohXLm18w
|
||||
+5AF+ES3DOQ6ixu3DTf0D+6qrDuK+prdX8ivcdTQVNOQ+MIZeGSc6NWWOTaMGJ3lg
|
||||
+aZIxJUGdo6E7GBGiC1YTjgFKFbHzek1LRTh/LX3vbSudxwaG0HQxwsU9T4DWiMqa
|
||||
+Fkf2KteLEUA6HrR+0XlAZrhwoqAmrJ+8lCFX3V0gE9lpENfVHlFXDGyx10DpTB28
|
||||
+DdjnY3F7EPWNzwf9P3oNT69CKW3Bk6VVr3ROOJtDxVu1ioWo3TaXltQ0VOnap2Pu
|
||||
+sa5wfrpfwBDuAS9JCDg4ttNp2nW3F7tgXC6xPqw5pvGwUppEw9XNrqV8TZrxduuv
|
||||
+rQ3NyZ7KSzIpmFlD3UwV/fGfz3UQmHS6Ng1evrUID9DjfYNfRqSGIGjDfxGtYD+j
|
||||
+Z1gLJZuhjJpNtwBkKRtlNtrCWCJK2hidK/foxwD7kwAPo2I9FjpltxCRywZUs07X
|
||||
+KwXTfBR9v6ij1LV6K58hFS+8ezZyZ05CeVBFkMQdclTOSfuPxlMkQOtjp8QWDj+F
|
||||
+j/MYziT5KBkHvcbrjdRtUJIAi4N7zCsPZtjik918AK1WBNRVqPbrgq/XSEXMfuvs
|
||||
+6JbfK0B76vdBDRtJFC1JsvnIrGbUztxXzyQwFLaR/AjVJqpVlysLWzPKWVX6/+SJ
|
||||
+u1NQOl2E8P6ycyBsuGnO89p0S4F8cMRcI2X1XQsZ7/q0NBrOMaEp5T3SrWo9GiQ3
|
||||
+o2SBdbs3Y6MBPBtTu977Z/0RO63J3M5i2tjUiDfrFy7+VRLKr7qQ7JibohyB8QaR
|
||||
+9tedgjn2f+of7PnP/PEl1cCphUZeHM7QKUMPT8dbqwmKtlYY43EHXcvNOT5IBk3X
|
||||
+9lwJoZk/B2i+ZMRNSP34ztAwtxmasPt6RAWGQpWCn9qmttAHAnMfDqe7F7jVR6rS
|
||||
+u58=
|
||||
+-----END CERTIFICATE-----`
|
||||
+
|
||||
+func TestHandshakeRSATooBig(t *testing.T) {
|
||||
+ testCert, _ := pem.Decode([]byte(largeRSAKeyCertPEM))
|
||||
+
|
||||
+ c := &Conn{conn: &discardConn{}, config: testConfig.Clone()}
|
||||
+
|
||||
+ expectedErr := "tls: server sent certificate containing RSA key larger than 8192 bits"
|
||||
+ err := c.verifyServerCertificate([][]byte{testCert.Bytes})
|
||||
+ if err == nil || err.Error() != expectedErr {
|
||||
+ t.Errorf("Conn.verifyServerCertificate unexpected error: want %q, got %q", expectedErr, err)
|
||||
+ }
|
||||
+
|
||||
+ expectedErr = "tls: client sent certificate containing RSA key larger than 8192 bits"
|
||||
+ err = c.processCertsFromClient(Certificate{Certificate: [][]byte{testCert.Bytes}})
|
||||
+ if err == nil || err.Error() != expectedErr {
|
||||
+ t.Errorf("Conn.processCertsFromClient unexpected error: want %q, got %q", expectedErr, err)
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
|
||||
index 8d51e7e55f..a5d8f4a9a8 100644
|
||||
--- a/src/crypto/tls/handshake_server.go
|
||||
+++ b/src/crypto/tls/handshake_server.go
|
||||
@@ -812,6 +812,10 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
|
||||
c.sendAlert(alertBadCertificate)
|
||||
return errors.New("tls: failed to parse client certificate: " + err.Error())
|
||||
}
|
||||
+ if certs[i].PublicKeyAlgorithm == x509.RSA && certs[i].PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
|
||||
+ c.sendAlert(alertBadCertificate)
|
||||
+ return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
|
||||
+ }
|
||||
}
|
||||
|
||||
if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {
|
||||
--
|
||||
2.33.0
|
||||
|
||||
267
0050-Backport-html-template-support-HTML-like-comments-in.patch
Normal file
267
0050-Backport-html-template-support-HTML-like-comments-in.patch
Normal file
@ -0,0 +1,267 @@
|
||||
From fc0e2bd566a8e8777acc824211f6027184840a49 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Fri, 4 Aug 2023 03:24:13 +0800
|
||||
Subject: [PATCH 1/2] [Backport] html/template: support HTML-like comments in
|
||||
script contexts
|
||||
|
||||
Reference: https://open.codehub.huawei.com/OpenSourceCenter/golang/go/merge_requests/89
|
||||
Conflict: NA
|
||||
|
||||
Per Appendix B.1.1 of the ECMAScript specification, support HTML-like
|
||||
comments in script contexts. Also per section 12.5, support hashbang
|
||||
comments. This brings our parsing in-line with how browsers treat these
|
||||
comment types.
|
||||
|
||||
Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
|
||||
reporting this issue.
|
||||
|
||||
Note: The upstream does not submit this change to go1.17 according to the rules of MinorReleases.
|
||||
Corego3.x are based on go1.17.8. Therefore, it need to submit the change to corego3.x.
|
||||
|
||||
Edited-by: machangwang m00509938
|
||||
|
||||
Fixes #62196
|
||||
Fixes #62395
|
||||
Fixes CVE-2023-39318
|
||||
|
||||
Change-Id: Id512702c5de3ae46cf648e268cb10e1eb392a181
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976593
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014620
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/526098
|
||||
Run-TryBot: Cherry Mui <cherryyz@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
|
||||
Signed-off-by: Ma Chang Wang machangwang@huawei.com
|
||||
---
|
||||
src/html/template/context.go | 6 ++-
|
||||
src/html/template/escape.go | 5 +-
|
||||
src/html/template/escape_test.go | 10 ++++
|
||||
src/html/template/state_string.go | 26 +++++-----
|
||||
src/html/template/transition.go | 80 ++++++++++++++++++++-----------
|
||||
5 files changed, 84 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/src/html/template/context.go b/src/html/template/context.go
|
||||
index a67b5a7871..472b5a9772 100644
|
||||
--- a/src/html/template/context.go
|
||||
+++ b/src/html/template/context.go
|
||||
@@ -124,6 +124,10 @@ const (
|
||||
stateJSBlockCmt
|
||||
// stateJSLineCmt occurs inside a JavaScript // line comment.
|
||||
stateJSLineCmt
|
||||
+ // stateJSHTMLOpenCmt occurs inside a JavaScript <!-- HTML-like comment.
|
||||
+ stateJSHTMLOpenCmt
|
||||
+ // stateJSHTMLCloseCmt occurs inside a JavaScript --> HTML-like comment.
|
||||
+ stateJSHTMLCloseCmt
|
||||
// stateCSS occurs inside a <style> element or style attribute.
|
||||
stateCSS
|
||||
// stateCSSDqStr occurs inside a CSS double quoted string.
|
||||
@@ -151,7 +155,7 @@ const (
|
||||
// authors & maintainers, not for end-users or machines.
|
||||
func isComment(s state) bool {
|
||||
switch s {
|
||||
- case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
|
||||
+ case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt, stateCSSBlockCmt, stateCSSLineCmt:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
diff --git a/src/html/template/escape.go b/src/html/template/escape.go
|
||||
index bdccc65a57..3249c67008 100644
|
||||
--- a/src/html/template/escape.go
|
||||
+++ b/src/html/template/escape.go
|
||||
@@ -700,9 +700,12 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
|
||||
if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
|
||||
// Preserve the portion between written and the comment start.
|
||||
cs := i1 - 2
|
||||
- if c1.state == stateHTMLCmt {
|
||||
+ if c1.state == stateHTMLCmt || c1.state == stateJSHTMLOpenCmt {
|
||||
// "<!--" instead of "/*" or "//"
|
||||
cs -= 2
|
||||
+ } else if c1.state == stateJSHTMLCloseCmt {
|
||||
+ // "-->" instead of "/*" or "//"
|
||||
+ cs -= 1
|
||||
}
|
||||
b.Write(s[written:cs])
|
||||
written = i1
|
||||
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
|
||||
index 3e17aee8f2..e38888a13f 100644
|
||||
--- a/src/html/template/escape_test.go
|
||||
+++ b/src/html/template/escape_test.go
|
||||
@@ -503,6 +503,16 @@ func TestEscape(t *testing.T) {
|
||||
"<script>var a/*b*///c\nd</script>",
|
||||
"<script>var a \nd</script>",
|
||||
},
|
||||
+ {
|
||||
+ "JS HTML-like comments",
|
||||
+ "<script>before <!-- beep\nbetween\nbefore-->boop\n</script>",
|
||||
+ "<script>before \nbetween\nbefore\n</script>",
|
||||
+ },
|
||||
+ {
|
||||
+ "JS hashbang comment",
|
||||
+ "<script>#! beep\n</script>",
|
||||
+ "<script>\n</script>",
|
||||
+ },
|
||||
{
|
||||
"CSS comments",
|
||||
"<style>p// paragraph\n" +
|
||||
diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go
|
||||
index 6fb1a6eeb0..be7a920511 100644
|
||||
--- a/src/html/template/state_string.go
|
||||
+++ b/src/html/template/state_string.go
|
||||
@@ -25,21 +25,23 @@ func _() {
|
||||
_ = x[stateJSRegexp-14]
|
||||
_ = x[stateJSBlockCmt-15]
|
||||
_ = x[stateJSLineCmt-16]
|
||||
- _ = x[stateCSS-17]
|
||||
- _ = x[stateCSSDqStr-18]
|
||||
- _ = x[stateCSSSqStr-19]
|
||||
- _ = x[stateCSSDqURL-20]
|
||||
- _ = x[stateCSSSqURL-21]
|
||||
- _ = x[stateCSSURL-22]
|
||||
- _ = x[stateCSSBlockCmt-23]
|
||||
- _ = x[stateCSSLineCmt-24]
|
||||
- _ = x[stateError-25]
|
||||
- _ = x[stateDead-26]
|
||||
+ _ = x[stateJSHTMLOpenCmt-17]
|
||||
+ _ = x[stateJSHTMLCloseCmt-18]
|
||||
+ _ = x[stateCSS-19]
|
||||
+ _ = x[stateCSSDqStr-20]
|
||||
+ _ = x[stateCSSSqStr-21]
|
||||
+ _ = x[stateCSSDqURL-22]
|
||||
+ _ = x[stateCSSSqURL-23]
|
||||
+ _ = x[stateCSSURL-24]
|
||||
+ _ = x[stateCSSBlockCmt-25]
|
||||
+ _ = x[stateCSSLineCmt-26]
|
||||
+ _ = x[stateError-27]
|
||||
+ _ = x[stateDead-28]
|
||||
}
|
||||
|
||||
-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
|
||||
+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
|
||||
|
||||
-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, 308, 317}
|
||||
+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 214, 233, 241, 254, 267, 280, 293, 304, 320, 335, 345, 354}
|
||||
|
||||
func (i state) String() string {
|
||||
if i >= state(len(_state_index)-1) {
|
||||
diff --git a/src/html/template/transition.go b/src/html/template/transition.go
|
||||
index 92eb351906..12aa4c41fe 100644
|
||||
--- a/src/html/template/transition.go
|
||||
+++ b/src/html/template/transition.go
|
||||
@@ -14,32 +14,34 @@ import (
|
||||
// the updated context and the number of bytes consumed from the front of the
|
||||
// input.
|
||||
var transitionFunc = [...]func(context, []byte) (context, int){
|
||||
- stateText: tText,
|
||||
- stateTag: tTag,
|
||||
- stateAttrName: tAttrName,
|
||||
- stateAfterName: tAfterName,
|
||||
- stateBeforeValue: tBeforeValue,
|
||||
- stateHTMLCmt: tHTMLCmt,
|
||||
- stateRCDATA: tSpecialTagEnd,
|
||||
- stateAttr: tAttr,
|
||||
- stateURL: tURL,
|
||||
- stateSrcset: tURL,
|
||||
- stateJS: tJS,
|
||||
- stateJSDqStr: tJSDelimited,
|
||||
- stateJSSqStr: tJSDelimited,
|
||||
- stateJSBqStr: tJSDelimited,
|
||||
- stateJSRegexp: tJSDelimited,
|
||||
- stateJSBlockCmt: tBlockCmt,
|
||||
- stateJSLineCmt: tLineCmt,
|
||||
- stateCSS: tCSS,
|
||||
- stateCSSDqStr: tCSSStr,
|
||||
- stateCSSSqStr: tCSSStr,
|
||||
- stateCSSDqURL: tCSSStr,
|
||||
- stateCSSSqURL: tCSSStr,
|
||||
- stateCSSURL: tCSSStr,
|
||||
- stateCSSBlockCmt: tBlockCmt,
|
||||
- stateCSSLineCmt: tLineCmt,
|
||||
- stateError: tError,
|
||||
+ stateText: tText,
|
||||
+ stateTag: tTag,
|
||||
+ stateAttrName: tAttrName,
|
||||
+ stateAfterName: tAfterName,
|
||||
+ stateBeforeValue: tBeforeValue,
|
||||
+ stateHTMLCmt: tHTMLCmt,
|
||||
+ stateRCDATA: tSpecialTagEnd,
|
||||
+ stateAttr: tAttr,
|
||||
+ stateURL: tURL,
|
||||
+ stateSrcset: tURL,
|
||||
+ stateJS: tJS,
|
||||
+ stateJSDqStr: tJSDelimited,
|
||||
+ stateJSSqStr: tJSDelimited,
|
||||
+ stateJSBqStr: tJSDelimited,
|
||||
+ stateJSRegexp: tJSDelimited,
|
||||
+ stateJSBlockCmt: tBlockCmt,
|
||||
+ stateJSLineCmt: tLineCmt,
|
||||
+ stateJSHTMLOpenCmt: tLineCmt,
|
||||
+ stateJSHTMLCloseCmt: tLineCmt,
|
||||
+ stateCSS: tCSS,
|
||||
+ stateCSSDqStr: tCSSStr,
|
||||
+ stateCSSSqStr: tCSSStr,
|
||||
+ stateCSSDqURL: tCSSStr,
|
||||
+ stateCSSSqURL: tCSSStr,
|
||||
+ stateCSSURL: tCSSStr,
|
||||
+ stateCSSBlockCmt: tBlockCmt,
|
||||
+ stateCSSLineCmt: tLineCmt,
|
||||
+ stateError: tError,
|
||||
}
|
||||
|
||||
var commentStart = []byte("<!--")
|
||||
@@ -263,7 +265,7 @@ func tURL(c context, s []byte) (context, int) {
|
||||
|
||||
// tJS is the context transition function for the JS state.
|
||||
func tJS(c context, s []byte) (context, int) {
|
||||
- i := bytes.IndexAny(s, "\"`'/")
|
||||
+ i := bytes.IndexAny(s, "\"`'/<-#")
|
||||
if i == -1 {
|
||||
// Entire input is non string, comment, regexp tokens.
|
||||
c.jsCtx = nextJSCtx(s, c.jsCtx)
|
||||
@@ -293,6 +295,26 @@ func tJS(c context, s []byte) (context, int) {
|
||||
err: errorf(ErrSlashAmbig, nil, 0, "'/' could start a division or regexp: %.32q", s[i:]),
|
||||
}, len(s)
|
||||
}
|
||||
+ // ECMAScript supports HTML style comments for legacy reasons, see Appendix
|
||||
+ // B.1.1 "HTML-like Comments". The handling of these comments is somewhat
|
||||
+ // confusing. Multi-line comments are not supported, i.e. anything on lines
|
||||
+ // between the opening and closing tokens is not considered a comment, but
|
||||
+ // anything following the opening or closing token, on the same line, is
|
||||
+ // ignored. As such we simply treat any line prefixed with "<!--" or "-->"
|
||||
+ // as if it were actually prefixed with "//" and move on.
|
||||
+ case '<':
|
||||
+ if i+3 < len(s) && bytes.Equal(commentStart, s[i:i+4]) {
|
||||
+ c.state, i = stateJSHTMLOpenCmt, i+3
|
||||
+ }
|
||||
+ case '-':
|
||||
+ if i+2 < len(s) && bytes.Equal(commentEnd, s[i:i+3]) {
|
||||
+ c.state, i = stateJSHTMLCloseCmt, i+2
|
||||
+ }
|
||||
+ // ECMAScript also supports "hashbang" comment lines, see Section 12.5.
|
||||
+ case '#':
|
||||
+ if i+1 < len(s) && s[i+1] == '!' {
|
||||
+ c.state, i = stateJSLineCmt, i+1
|
||||
+ }
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
@@ -372,12 +394,12 @@ func tBlockCmt(c context, s []byte) (context, int) {
|
||||
return c, i + 2
|
||||
}
|
||||
|
||||
-// tLineCmt is the context transition function for //comment states.
|
||||
+// tLineCmt is the context transition function for //comment states, and the JS HTML-like comment state.
|
||||
func tLineCmt(c context, s []byte) (context, int) {
|
||||
var lineTerminators string
|
||||
var endState state
|
||||
switch c.state {
|
||||
- case stateJSLineCmt:
|
||||
+ case stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt:
|
||||
lineTerminators, endState = "\n\r\u2028\u2029", stateJS
|
||||
case stateCSSLineCmt:
|
||||
lineTerminators, endState = "\n\f\r", stateCSS
|
||||
--
|
||||
2.33.0
|
||||
259
0051-Backport-html-template-properly-handle-special-tags-.patch
Normal file
259
0051-Backport-html-template-properly-handle-special-tags-.patch
Normal file
@ -0,0 +1,259 @@
|
||||
From 015ed76f8637206669be945cb7d1c4315b5a0110 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Thu, 3 Aug 2023 12:28:28 -0700
|
||||
Subject: [PATCH 2/2] [Backport] html/template: properly handle special tags
|
||||
within the script context
|
||||
|
||||
Reference: https://open.codehub.huawei.com/OpenSourceCenter/golang/go/merge_requests/94
|
||||
Conflict: NA
|
||||
|
||||
The HTML specification has incredibly complex rules for how to handle
|
||||
"<!--", "<script", and "</script" when they appear within literals in
|
||||
the script context. Rather than attempting to apply these restrictions
|
||||
(which require a significantly more complex state machine) we apply
|
||||
the workaround suggested in section 4.12.1.3 of the HTML specification [1].
|
||||
|
||||
More precisely, when "<!--", "<script", and "</script" appear within
|
||||
literals (strings and regular expressions, ignoring comments since we
|
||||
already elide their content) we replace the "<" with "\x3C". This avoids
|
||||
the unintuitive behavior that using these tags within literals can cause,
|
||||
by simply preventing the rendered content from triggering it. This may
|
||||
break some correct usages of these tags, but on balance is more likely
|
||||
to prevent XSS attacks where users are unknowingly either closing or not
|
||||
closing the script blocks where they think they are.
|
||||
|
||||
Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
|
||||
reporting this issue.
|
||||
|
||||
Note: The upstream does not submit this change to go1.17 according to the rules of MinorReleases.
|
||||
Corego3.x are based on go1.17.8. Therefore, it need to submit the change to corego3.x.
|
||||
|
||||
Edited-by: machangwang m00509938
|
||||
|
||||
Fixes #62197
|
||||
Fixes #62397
|
||||
Fixes CVE-2023-39319
|
||||
|
||||
[1] https://html.spec.whatwg.org/#restrictions-for-contents-of-script-elements
|
||||
|
||||
Change-Id: Iab57b0532694827e3eddf57a7497ba1fab1746dc
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976594
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014621
|
||||
TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/526099
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
Run-TryBot: Cherry Mui <cherryyz@google.com>
|
||||
|
||||
Signed-off-by: Ma Chang Wang machangwang@huawei.com
|
||||
---
|
||||
src/go/build/deps_test.go | 6 ++--
|
||||
src/html/template/context.go | 14 ++++++++++
|
||||
src/html/template/escape.go | 26 ++++++++++++++++++
|
||||
src/html/template/escape_test.go | 47 +++++++++++++++++++++++++++++++-
|
||||
src/html/template/transition.go | 15 ++++++++++
|
||||
5 files changed, 104 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
|
||||
index 610fba2da9..e56cd587ff 100644
|
||||
--- a/src/go/build/deps_test.go
|
||||
+++ b/src/go/build/deps_test.go
|
||||
@@ -255,15 +255,15 @@ var depsRules = `
|
||||
< text/template
|
||||
< internal/lazytemplate;
|
||||
|
||||
- encoding/json, html, text/template
|
||||
- < html/template;
|
||||
-
|
||||
# regexp
|
||||
FMT
|
||||
< regexp/syntax
|
||||
< regexp
|
||||
< internal/lazyregexp;
|
||||
|
||||
+ encoding/json, html, text/template, regexp
|
||||
+ < html/template;
|
||||
+
|
||||
# suffix array
|
||||
encoding/binary, regexp
|
||||
< index/suffixarray;
|
||||
diff --git a/src/html/template/context.go b/src/html/template/context.go
|
||||
index 472b5a9772..8c3cc4709e 100644
|
||||
--- a/src/html/template/context.go
|
||||
+++ b/src/html/template/context.go
|
||||
@@ -170,6 +170,20 @@ func isInTag(s state) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
+// isInScriptLiteral returns true if s is one of the literal states within a
|
||||
+// <script> tag, and as such occurances of "<!--", "<script", and "</script"
|
||||
+// need to be treated specially.
|
||||
+func isInScriptLiteral(s state) bool {
|
||||
+ // Ignore the comment states (stateJSBlockCmt, stateJSLineCmt,
|
||||
+ // stateJSHTMLOpenCmt, stateJSHTMLCloseCmt) because their content is already
|
||||
+ // omitted from the output.
|
||||
+ switch s {
|
||||
+ case stateJSDqStr, stateJSSqStr, stateJSBqStr, stateJSRegexp:
|
||||
+ return true
|
||||
+ }
|
||||
+ return false
|
||||
+}
|
||||
+
|
||||
// delim is the delimiter that will end the current HTML attribute.
|
||||
type delim uint8
|
||||
|
||||
diff --git a/src/html/template/escape.go b/src/html/template/escape.go
|
||||
index 3249c67008..b0085ceccc 100644
|
||||
--- a/src/html/template/escape.go
|
||||
+++ b/src/html/template/escape.go
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"html"
|
||||
"internal/godebug"
|
||||
"io"
|
||||
+ "regexp"
|
||||
"text/template"
|
||||
"text/template/parse"
|
||||
)
|
||||
@@ -652,6 +653,26 @@ var delimEnds = [...]string{
|
||||
delimSpaceOrTagEnd: " \t\n\f\r>",
|
||||
}
|
||||
|
||||
+var (
|
||||
+ // Per WHATWG HTML specification, section 4.12.1.3, there are extremely
|
||||
+ // complicated rules for how to handle the set of opening tags <!--,
|
||||
+ // <script, and </script when they appear in JS literals (i.e. strings,
|
||||
+ // regexs, and comments). The specification suggests a simple solution,
|
||||
+ // rather than implementing the arcane ABNF, which involves simply escaping
|
||||
+ // the opening bracket with \x3C. We use the below regex for this, since it
|
||||
+ // makes doing the case-insensitive find-replace much simpler.
|
||||
+ specialScriptTagRE = regexp.MustCompile("(?i)<(script|/script|!--)")
|
||||
+ specialScriptTagReplacement = []byte("\\x3C$1")
|
||||
+)
|
||||
+
|
||||
+func containsSpecialScriptTag(s []byte) bool {
|
||||
+ return specialScriptTagRE.Match(s)
|
||||
+}
|
||||
+
|
||||
+func escapeSpecialScriptTags(s []byte) []byte {
|
||||
+ return specialScriptTagRE.ReplaceAll(s, specialScriptTagReplacement)
|
||||
+}
|
||||
+
|
||||
var doctypeBytes = []byte("<!DOCTYPE")
|
||||
|
||||
// escapeText escapes a text template node.
|
||||
@@ -710,6 +731,11 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
|
||||
b.Write(s[written:cs])
|
||||
written = i1
|
||||
}
|
||||
+ if isInScriptLiteral(c.state) && containsSpecialScriptTag(s[i:i1]) {
|
||||
+ b.Write(s[written:i])
|
||||
+ b.Write(escapeSpecialScriptTags(s[i:i1]))
|
||||
+ written = i1
|
||||
+ }
|
||||
if i == i1 && c.state == c1.state {
|
||||
panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
|
||||
}
|
||||
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
|
||||
index e38888a13f..2f9f4c21f0 100644
|
||||
--- a/src/html/template/escape_test.go
|
||||
+++ b/src/html/template/escape_test.go
|
||||
@@ -513,6 +513,21 @@ func TestEscape(t *testing.T) {
|
||||
"<script>#! beep\n</script>",
|
||||
"<script>\n</script>",
|
||||
},
|
||||
+ {
|
||||
+ "Special tags in <script> string literals",
|
||||
+ `<script>var a = "asd < 123 <!-- 456 < fgh <script jkl < 789 </script"</script>`,
|
||||
+ `<script>var a = "asd < 123 \x3C!-- 456 < fgh \x3Cscript jkl < 789 \x3C/script"</script>`,
|
||||
+ },
|
||||
+ {
|
||||
+ "Special tags in <script> string literals (mixed case)",
|
||||
+ `<script>var a = "<!-- <ScripT </ScripT"</script>`,
|
||||
+ `<script>var a = "\x3C!-- \x3CScripT \x3C/ScripT"</script>`,
|
||||
+ },
|
||||
+ {
|
||||
+ "Special tags in <script> regex literals (mixed case)",
|
||||
+ `<script>var a = /<!-- <ScripT </ScripT/</script>`,
|
||||
+ `<script>var a = /\x3C!-- \x3CScripT \x3C/ScripT/</script>`,
|
||||
+ },
|
||||
{
|
||||
"CSS comments",
|
||||
"<style>p// paragraph\n" +
|
||||
@@ -1509,8 +1524,38 @@ func TestEscapeText(t *testing.T) {
|
||||
context{state: stateJS, element: elementScript},
|
||||
},
|
||||
{
|
||||
+ // <script and </script tags are escaped, so </script> should not
|
||||
+ // cause us to exit the JS state.
|
||||
`<script>document.write("<script>alert(1)</script>");`,
|
||||
- context{state: stateText},
|
||||
+ context{state: stateJS, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<script>`,
|
||||
+ context{state: stateJSDqStr, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<script>alert(1)</script>`,
|
||||
+ context{state: stateJSDqStr, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<script>alert(1)<!--`,
|
||||
+ context{state: stateJSDqStr, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<script>alert(1)</Script>");`,
|
||||
+ context{state: stateJS, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<!--");`,
|
||||
+ context{state: stateJS, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>let a = /</script`,
|
||||
+ context{state: stateJSRegexp, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>let a = /</script/`,
|
||||
+ context{state: stateJS, element: elementScript, jsCtx: jsCtxDivOp},
|
||||
},
|
||||
{
|
||||
`<script type="text/template">`,
|
||||
diff --git a/src/html/template/transition.go b/src/html/template/transition.go
|
||||
index 12aa4c41fe..3d2a37cdd9 100644
|
||||
--- a/src/html/template/transition.go
|
||||
+++ b/src/html/template/transition.go
|
||||
@@ -214,6 +214,11 @@ var (
|
||||
// element states.
|
||||
func tSpecialTagEnd(c context, s []byte) (context, int) {
|
||||
if c.element != elementNone {
|
||||
+ // script end tags ("</script") within script literals are ignored, so that
|
||||
+ // we can properly escape them.
|
||||
+ if c.element == elementScript && (isInScriptLiteral(c.state) || isComment(c.state)) {
|
||||
+ return c, len(s)
|
||||
+ }
|
||||
if i := indexTagEnd(s, specialTagEndMarkers[c.element]); i != -1 {
|
||||
return context{}, i
|
||||
}
|
||||
@@ -353,6 +358,16 @@ func tJSDelimited(c context, s []byte) (context, int) {
|
||||
inCharset = true
|
||||
case ']':
|
||||
inCharset = false
|
||||
+ case '/':
|
||||
+ // If "</script" appears in a regex literal, the '/' should not
|
||||
+ // close the regex literal, and it will later be escaped to
|
||||
+ // "\x3C/script" in escapeText.
|
||||
+ if i > 0 && i+7 <= len(s) && bytes.Compare(bytes.ToLower(s[i-1:i+7]), []byte("</script")) == 0 {
|
||||
+ i++
|
||||
+ } else if !inCharset {
|
||||
+ c.state, c.jsCtx = stateJS, jsCtxDivOp
|
||||
+ return c, i + 1
|
||||
+ }
|
||||
default:
|
||||
// end delimiter
|
||||
if !inCharset {
|
||||
--
|
||||
2.33.0
|
||||
140
0052-Backport-cmd-compile-use-absolute-file-name-in-isCgo.patch
Normal file
140
0052-Backport-cmd-compile-use-absolute-file-name-in-isCgo.patch
Normal file
@ -0,0 +1,140 @@
|
||||
From a56df8ee0ed2cd76c939f916d5f72f281f902f7c Mon Sep 17 00:00:00 2001
|
||||
From: Ian Lance Taylor <iant@golang.org>
|
||||
Date: Thu, 21 Sep 2023 07:16:29 +0800
|
||||
Subject: [PATCH] [Backport] cmd/compile: use absolute file name in isCgo check
|
||||
|
||||
Offering: Cloud Core Network
|
||||
CVE: CVE-2023-39323
|
||||
Reference: https://go-review.googlesource.com/c/go/+/533195
|
||||
|
||||
Note: The upstream does not submit this change to go1.17 according to the rules of MinorReleases.
|
||||
Corego3.x are based on go1.17.8. Therefore, it need to submit the change to corego3.x.
|
||||
|
||||
Edited-by: machangwang m00509938
|
||||
|
||||
For #23672
|
||||
Updates #63211
|
||||
Fixes #63213
|
||||
Fixes CVE-2023-39323
|
||||
|
||||
Change-Id: I4586a69e1b2560036afec29d53e53cf25e6c7352
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2032884
|
||||
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
(cherry picked from commit 9b19e751918dd218035811b1ef83a8c2693b864a)
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2037629
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/533195
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
Reviewed-by: Ian Lance Taylor <iant@google.com>
|
||||
TryBot-Bypass: Michael Pratt <mpratt@google.com>
|
||||
Reviewed-by: Than McIntosh <thanm@google.com>
|
||||
Signed-off-by: Ma Chang Wang machangwang@huawei.com
|
||||
---
|
||||
misc/cgo/errors/errors_test.go | 32 ++++++++++++++++++-------
|
||||
misc/cgo/errors/testdata/err5.go | 11 +++++++++
|
||||
src/cmd/compile/internal/noder/noder.go | 8 ++++++-
|
||||
3 files changed, 41 insertions(+), 10 deletions(-)
|
||||
create mode 100644 misc/cgo/errors/testdata/err5.go
|
||||
|
||||
diff --git a/misc/cgo/errors/errors_test.go b/misc/cgo/errors/errors_test.go
|
||||
index 68a30a44fe..dd60a98e8e 100644
|
||||
--- a/misc/cgo/errors/errors_test.go
|
||||
+++ b/misc/cgo/errors/errors_test.go
|
||||
@@ -20,6 +20,13 @@ func path(file string) string {
|
||||
return filepath.Join("testdata", file)
|
||||
}
|
||||
|
||||
+func bytesCut(s, sep []byte) (before, after []byte, found bool) {
|
||||
+ if i := bytes.Index(s, sep); i >= 0 {
|
||||
+ return s[:i], s[i+len(sep):], true
|
||||
+ }
|
||||
+ return s, nil, false
|
||||
+}
|
||||
+
|
||||
func check(t *testing.T, file string) {
|
||||
t.Run(file, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -36,17 +43,23 @@ func check(t *testing.T, file string) {
|
||||
continue
|
||||
}
|
||||
|
||||
- frags := bytes.SplitAfterN(line, []byte("ERROR HERE: "), 2)
|
||||
- if len(frags) == 1 {
|
||||
- continue
|
||||
+ if _, frag, ok := bytesCut(line, []byte("ERROR HERE: ")); ok {
|
||||
+ re, err := regexp.Compile(fmt.Sprintf(":%d:.*%s", i+1, frag))
|
||||
+ if err != nil {
|
||||
+ t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frag)
|
||||
+ continue
|
||||
+ }
|
||||
+ errors = append(errors, re)
|
||||
}
|
||||
- frag := fmt.Sprintf(":%d:.*%s", i+1, frags[1])
|
||||
- re, err := regexp.Compile(frag)
|
||||
- if err != nil {
|
||||
- t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frags[1])
|
||||
- continue
|
||||
+
|
||||
+ if _, frag, ok := bytesCut(line, []byte("ERROR MESSAGE: ")); ok {
|
||||
+ re, err := regexp.Compile(string(frag))
|
||||
+ if err != nil {
|
||||
+ t.Errorf("Invalid regexp after `ERROR MESSAGE: `: %#q", frag)
|
||||
+ continue
|
||||
+ }
|
||||
+ errors = append(errors, re)
|
||||
}
|
||||
- errors = append(errors, re)
|
||||
}
|
||||
if len(errors) == 0 {
|
||||
t.Fatalf("cannot find ERROR HERE")
|
||||
@@ -107,6 +120,7 @@ func TestReportsTypeErrors(t *testing.T) {
|
||||
for _, file := range []string{
|
||||
"err1.go",
|
||||
"err2.go",
|
||||
+ "err5.go",
|
||||
"issue11097a.go",
|
||||
"issue11097b.go",
|
||||
"issue18452.go",
|
||||
diff --git a/misc/cgo/errors/testdata/err5.go b/misc/cgo/errors/testdata/err5.go
|
||||
new file mode 100644
|
||||
index 0000000000..c12a290d38
|
||||
--- /dev/null
|
||||
+++ b/misc/cgo/errors/testdata/err5.go
|
||||
@@ -0,0 +1,11 @@
|
||||
+// Copyright 2023 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.
|
||||
+
|
||||
+package main
|
||||
+
|
||||
+//line /tmp/_cgo_.go:1
|
||||
+//go:cgo_dynamic_linker "/elf/interp"
|
||||
+// ERROR MESSAGE: only allowed in cgo-generated code
|
||||
+
|
||||
+func main() {}
|
||||
diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go
|
||||
index 5fcad096c2..b802d22bc1 100644
|
||||
--- a/src/cmd/compile/internal/noder/noder.go
|
||||
+++ b/src/cmd/compile/internal/noder/noder.go
|
||||
@@ -1690,8 +1690,14 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
|
||||
// contain cgo directives, and for security reasons
|
||||
// (primarily misuse of linker flags), other files are not.
|
||||
// See golang.org/issue/23672.
|
||||
+// Note that cmd/go ignores files whose names start with underscore,
|
||||
+// so the only _cgo_ files we will see from cmd/go are generated by cgo.
|
||||
+// It's easy to bypass this check by calling the compiler directly;
|
||||
+// we only protect against uses by cmd/go.
|
||||
func isCgoGeneratedFile(pos syntax.Pos) bool {
|
||||
- return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Filename()))), "_cgo_")
|
||||
+ // We need the absolute file, independent of //line directives,
|
||||
+ // so we call pos.Base().Pos().
|
||||
+ return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Pos().Base().Filename()))), "_cgo_")
|
||||
}
|
||||
|
||||
// safeArg reports whether arg is a "safe" command-line argument,
|
||||
--
|
||||
2.28.0.windows.1
|
||||
|
||||
147
0053-CVE-2023-39325-net-http-regenerate-h2_bundle.go.patch
Normal file
147
0053-CVE-2023-39325-net-http-regenerate-h2_bundle.go.patch
Normal file
@ -0,0 +1,147 @@
|
||||
From 6dc693737f84785a30238ca7640ad8ba605c0eac Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Sat, 7 Oct 2023 05:16:27 +0800
|
||||
Subject: [PATCH] [Backport] net/http: regenerate h2_bundle.go
|
||||
|
||||
Offering: Cloud Core Network
|
||||
CVE: CVE-2023-39325
|
||||
Reference: https://go-review.googlesource.com/c/go/+/534255
|
||||
|
||||
Pull in a security fix from x/net/http2:
|
||||
http2: limit maximum handler goroutines to MaxConcurrentStreamso
|
||||
|
||||
Note: The upstream does not submit this change to go1.17 according to the rules of MinorReleases.
|
||||
Corego3.x are based on go1.17.8. Therefore, it need to submit the change to corego3.x.
|
||||
|
||||
Edited-by: machangwang m00509938
|
||||
|
||||
For #63417
|
||||
Fixes #63426
|
||||
Fixes CVE-2023-39325
|
||||
|
||||
Change-Id: I6e32397323cd9b4114c990fcc9d19557a7f5f619
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2047401
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
|
||||
Run-TryBot: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Ian Cottrell <iancottrell@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/534255
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-by: Michael Pratt <mpratt@google.com>
|
||||
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Signed-off-by: Ma Chang Wang machangwang@huawei.com
|
||||
---
|
||||
src/net/http/h2_bundle.go | 62 +++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 60 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
|
||||
index 5433ebdc51..b87d14b6ea 100644
|
||||
--- a/src/net/http/h2_bundle.go
|
||||
+++ b/src/net/http/h2_bundle.go
|
||||
@@ -4181,9 +4181,11 @@ type http2serverConn struct {
|
||||
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
|
||||
curClientStreams uint32 // number of open streams initiated by the client
|
||||
curPushedStreams uint32 // number of open streams initiated by server push
|
||||
+ curHandlers uint32 // number of running handler goroutines
|
||||
maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
|
||||
maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
|
||||
streams map[uint32]*http2stream
|
||||
+ unstartedHandlers []http2unstartedHandler
|
||||
initialStreamSendWindowSize int32
|
||||
maxFrameSize int32
|
||||
headerTableSize uint32
|
||||
@@ -4577,6 +4579,8 @@ func (sc *http2serverConn) serve() {
|
||||
return
|
||||
case http2gracefulShutdownMsg:
|
||||
sc.startGracefulShutdownInternal()
|
||||
+ case http2handlerDoneMsg:
|
||||
+ sc.handlerDone()
|
||||
default:
|
||||
panic("unknown timer")
|
||||
}
|
||||
@@ -4622,6 +4626,7 @@ var (
|
||||
http2idleTimerMsg = new(http2serverMessage)
|
||||
http2shutdownTimerMsg = new(http2serverMessage)
|
||||
http2gracefulShutdownMsg = new(http2serverMessage)
|
||||
+ http2handlerDoneMsg = new(http2serverMessage)
|
||||
)
|
||||
|
||||
func (sc *http2serverConn) onSettingsTimer() { sc.sendServeMsg(http2settingsTimerMsg) }
|
||||
@@ -5584,8 +5589,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
|
||||
sc.conn.SetReadDeadline(time.Time{})
|
||||
}
|
||||
|
||||
- go sc.runHandler(rw, req, handler)
|
||||
- return nil
|
||||
+ return sc.scheduleHandler(id, rw, req, handler)
|
||||
}
|
||||
|
||||
func (st *http2stream) processTrailerHeaders(f *http2MetaHeadersFrame) error {
|
||||
@@ -5832,8 +5836,62 @@ func (sc *http2serverConn) newWriterAndRequestNoBody(st *http2stream, rp http2re
|
||||
return rw, req, nil
|
||||
}
|
||||
|
||||
+type http2unstartedHandler struct {
|
||||
+ streamID uint32
|
||||
+ rw *http2responseWriter
|
||||
+ req *Request
|
||||
+ handler func(ResponseWriter, *Request)
|
||||
+}
|
||||
+
|
||||
+// scheduleHandler starts a handler goroutine,
|
||||
+// or schedules one to start as soon as an existing handler finishes.
|
||||
+func (sc *http2serverConn) scheduleHandler(streamID uint32, rw *http2responseWriter, req *Request, handler func(ResponseWriter, *Request)) error {
|
||||
+ sc.serveG.check()
|
||||
+ maxHandlers := sc.advMaxStreams
|
||||
+ if sc.curHandlers < maxHandlers {
|
||||
+ sc.curHandlers++
|
||||
+ go sc.runHandler(rw, req, handler)
|
||||
+ return nil
|
||||
+ }
|
||||
+ if len(sc.unstartedHandlers) > int(4*sc.advMaxStreams) {
|
||||
+ return http2ConnectionError(http2ErrCodeEnhanceYourCalm)
|
||||
+ }
|
||||
+ sc.unstartedHandlers = append(sc.unstartedHandlers, http2unstartedHandler{
|
||||
+ streamID: streamID,
|
||||
+ rw: rw,
|
||||
+ req: req,
|
||||
+ handler: handler,
|
||||
+ })
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (sc *http2serverConn) handlerDone() {
|
||||
+ sc.serveG.check()
|
||||
+ sc.curHandlers--
|
||||
+ i := 0
|
||||
+ maxHandlers := sc.advMaxStreams
|
||||
+ for ; i < len(sc.unstartedHandlers); i++ {
|
||||
+ u := sc.unstartedHandlers[i]
|
||||
+ if sc.streams[u.streamID] == nil {
|
||||
+ // This stream was reset before its goroutine had a chance to start.
|
||||
+ continue
|
||||
+ }
|
||||
+ if sc.curHandlers >= maxHandlers {
|
||||
+ break
|
||||
+ }
|
||||
+ sc.curHandlers++
|
||||
+ go sc.runHandler(u.rw, u.req, u.handler)
|
||||
+ sc.unstartedHandlers[i] = http2unstartedHandler{} // don't retain references
|
||||
+ }
|
||||
+ sc.unstartedHandlers = sc.unstartedHandlers[i:]
|
||||
+ if len(sc.unstartedHandlers) == 0 {
|
||||
+ sc.unstartedHandlers = nil
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// Run on its own goroutine.
|
||||
func (sc *http2serverConn) runHandler(rw *http2responseWriter, req *Request, handler func(ResponseWriter, *Request)) {
|
||||
+ defer sc.sendServeMsg(http2handlerDoneMsg)
|
||||
didPanic := true
|
||||
defer func() {
|
||||
rw.rws.stream.cancelCtx()
|
||||
--
|
||||
2.33.0
|
||||
|
||||
188
0054-CVE-2023-39326-net-http-limit-chunked-data-overhead.patch
Normal file
188
0054-CVE-2023-39326-net-http-limit-chunked-data-overhead.patch
Normal file
@ -0,0 +1,188 @@
|
||||
From 67b897648d6cac32b94b7e98a01588df5c7c59de Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Wed, 8 Nov 2023 02:47:56 +0800
|
||||
Subject: [PATCH 1/2] [Backport] net/http: limit chunked data overhead
|
||||
|
||||
Offering: Cloud Core Network
|
||||
CVE: CVE-2023-39326
|
||||
Reference: https://go-review.googlesource.com/c/go/+/547355
|
||||
Conflict: NA
|
||||
|
||||
The chunked transfer encoding adds some overhead to
|
||||
the content transferred. When writing one byte per
|
||||
chunk, for example, there are five bytes of overhead
|
||||
per byte of data transferred: "1\r\nX\r\n" to send "X".
|
||||
|
||||
Chunks may include "chunk extensions",
|
||||
which we skip over and do not use.
|
||||
For example: "1;chunk extension here\r\nX\r\n".
|
||||
|
||||
A malicious sender can use chunk extensions to add
|
||||
about 4k of overhead per byte of data.
|
||||
(The maximum chunk header line size we will accept.)
|
||||
|
||||
Track the amount of overhead read in chunked data,
|
||||
and produce an error if it seems excessive.
|
||||
|
||||
Note: The upstream does not submit this change to go1.17 according to the rules of MinorReleases.
|
||||
Corego3.x are based on go1.17.8. Therefore, it need to submit the change to corego3.x.
|
||||
|
||||
Edited-by: machangwang m00509938
|
||||
|
||||
Updates #64433
|
||||
Fixes #64434
|
||||
Fixes CVE-2023-39326
|
||||
|
||||
Change-Id: I40f8d70eb6f9575fb43f506eb19132ccedafcf39
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2076135
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
(cherry picked from commit 3473ae72ee66c60744665a24b2fde143e8964d4f)
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2095407
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/547355
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Signed-off-by: Ma Chang Wang machangwang@huawei.com
|
||||
---
|
||||
src/net/http/internal/chunked.go | 36 +++++++++++++---
|
||||
src/net/http/internal/chunked_test.go | 59 +++++++++++++++++++++++++++
|
||||
2 files changed, 89 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go
|
||||
index f06e5725f3..ddbaacbe5d 100644
|
||||
--- a/src/net/http/internal/chunked.go
|
||||
+++ b/src/net/http/internal/chunked.go
|
||||
@@ -39,7 +39,8 @@ type chunkedReader struct {
|
||||
n uint64 // unread bytes in chunk
|
||||
err error
|
||||
buf [2]byte
|
||||
- checkEnd bool // whether need to check for \r\n chunk footer
|
||||
+ checkEnd bool // whether need to check for \r\n chunk footer
|
||||
+ excess int64 // "excessive" chunk overhead, for malicious sender detection
|
||||
}
|
||||
|
||||
func (cr *chunkedReader) beginChunk() {
|
||||
@@ -49,10 +50,38 @@ func (cr *chunkedReader) beginChunk() {
|
||||
if cr.err != nil {
|
||||
return
|
||||
}
|
||||
+ cr.excess += int64(len(line)) + 2 // header, plus \r\n after the chunk data
|
||||
+ line = trimTrailingWhitespace(line)
|
||||
+ line, cr.err = removeChunkExtension(line)
|
||||
+ if cr.err != nil {
|
||||
+ return
|
||||
+ }
|
||||
cr.n, cr.err = parseHexUint(line)
|
||||
if cr.err != nil {
|
||||
return
|
||||
}
|
||||
+ // A sender who sends one byte per chunk will send 5 bytes of overhead
|
||||
+ // for every byte of data. ("1\r\nX\r\n" to send "X".)
|
||||
+ // We want to allow this, since streaming a byte at a time can be legitimate.
|
||||
+ //
|
||||
+ // A sender can use chunk extensions to add arbitrary amounts of additional
|
||||
+ // data per byte read. ("1;very long extension\r\nX\r\n" to send "X".)
|
||||
+ // We don't want to disallow extensions (although we discard them),
|
||||
+ // but we also don't want to allow a sender to reduce the signal/noise ratio
|
||||
+ // arbitrarily.
|
||||
+ //
|
||||
+ // We track the amount of excess overhead read,
|
||||
+ // and produce an error if it grows too large.
|
||||
+ //
|
||||
+ // Currently, we say that we're willing to accept 16 bytes of overhead per chunk,
|
||||
+ // plus twice the amount of real data in the chunk.
|
||||
+ cr.excess -= 16 + (2 * int64(cr.n))
|
||||
+ if cr.excess < 0 {
|
||||
+ cr.excess = 0
|
||||
+ }
|
||||
+ if cr.excess > 16*1024 {
|
||||
+ cr.err = errors.New("chunked encoding contains too much non-data")
|
||||
+ }
|
||||
if cr.n == 0 {
|
||||
cr.err = io.EOF
|
||||
}
|
||||
@@ -133,11 +162,6 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) {
|
||||
if len(p) >= maxLineLength {
|
||||
return nil, ErrLineTooLong
|
||||
}
|
||||
- p = trimTrailingWhitespace(p)
|
||||
- p, err = removeChunkExtension(p)
|
||||
- if err != nil {
|
||||
- return nil, err
|
||||
- }
|
||||
return p, nil
|
||||
}
|
||||
|
||||
diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go
|
||||
index 08152ed1e2..5fbeb0855f 100644
|
||||
--- a/src/net/http/internal/chunked_test.go
|
||||
+++ b/src/net/http/internal/chunked_test.go
|
||||
@@ -211,3 +211,62 @@ func TestChunkReadPartial(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
+
|
||||
+func TestChunkReaderTooMuchOverhead(t *testing.T) {
|
||||
+ // If the sender is sending 100x as many chunk header bytes as chunk data,
|
||||
+ // we should reject the stream at some point.
|
||||
+ chunk := []byte("1;")
|
||||
+ for i := 0; i < 100; i++ {
|
||||
+ chunk = append(chunk, 'a') // chunk extension
|
||||
+ }
|
||||
+ chunk = append(chunk, "\r\nX\r\n"...)
|
||||
+ const bodylen = 1 << 20
|
||||
+ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) {
|
||||
+ if i < bodylen {
|
||||
+ return chunk, nil
|
||||
+ }
|
||||
+ return []byte("0\r\n"), nil
|
||||
+ }})
|
||||
+ _, err := io.ReadAll(r)
|
||||
+ if err == nil {
|
||||
+ t.Fatalf("successfully read body with excessive overhead; want error")
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func TestChunkReaderByteAtATime(t *testing.T) {
|
||||
+ // Sending one byte per chunk should not trip the excess-overhead detection.
|
||||
+ const bodylen = 1 << 20
|
||||
+ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) {
|
||||
+ if i < bodylen {
|
||||
+ return []byte("1\r\nX\r\n"), nil
|
||||
+ }
|
||||
+ return []byte("0\r\n"), nil
|
||||
+ }})
|
||||
+ got, err := io.ReadAll(r)
|
||||
+ if err != nil {
|
||||
+ t.Errorf("unexpected error: %v", err)
|
||||
+ }
|
||||
+ if len(got) != bodylen {
|
||||
+ t.Errorf("read %v bytes, want %v", len(got), bodylen)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+type funcReader struct {
|
||||
+ f func(iteration int) ([]byte, error)
|
||||
+ i int
|
||||
+ b []byte
|
||||
+ err error
|
||||
+}
|
||||
+
|
||||
+func (r *funcReader) Read(p []byte) (n int, err error) {
|
||||
+ if len(r.b) == 0 && r.err == nil {
|
||||
+ r.b, r.err = r.f(r.i)
|
||||
+ r.i++
|
||||
+ }
|
||||
+ n = copy(p, r.b)
|
||||
+ r.b = r.b[n:]
|
||||
+ if len(r.b) > 0 {
|
||||
+ return n, nil
|
||||
+ }
|
||||
+ return n, r.err
|
||||
+}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,111 @@
|
||||
From e70b9fb5d55ff42d408fc9efea67fdb0c671d2b5 Mon Sep 17 00:00:00 2001
|
||||
From: "Bryan C. Mills" <bcmills@google.com>
|
||||
Date: Fri, 3 Nov 2023 03:06:35 +0800
|
||||
Subject: [PATCH 2/2] [Backport] cmd/go/internal/vcs: error out if the
|
||||
requested repo does not support a secure protocol
|
||||
|
||||
Offering: Cloud Core Network
|
||||
CVE: CVE-2023-45285
|
||||
Reference: https://go-review.googlesource.com/c/go/+/540335
|
||||
Conflict: NA
|
||||
|
||||
Updates #63845.
|
||||
Fixes #63972.
|
||||
|
||||
Change-Id: If86d6b13d3b55877b35c087112bd76388c9404b8
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/539321
|
||||
Reviewed-by: Michael Matloob matloob@golang.org
|
||||
LUCI-TryBot-Result: Go LUCI golang-scoped@luci-project-accounts.iam.gserviceaccount.com
|
||||
Reviewed-by: Roland Shoemaker roland@golang.org
|
||||
Auto-Submit: Bryan Mills bcmills@google.com
|
||||
(cherry picked from commit be26ae18caf7ddffca4073333f80d0d9e76483c3)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/540335
|
||||
Auto-Submit: Dmitri Shuralyov dmitshur@google.com
|
||||
Reviewed-by: Dmitri Shuralyov dmitshur@google.com
|
||||
Signed-off-by: wangbingyao 00557526 wangbingyao5@huawei.com
|
||||
---
|
||||
src/cmd/go/internal/vcs/vcs.go | 25 +++++++++++++----
|
||||
.../script/mod_insecure_issue63845.txt | 28 +++++++++++++++++++
|
||||
2 files changed, 47 insertions(+), 6 deletions(-)
|
||||
create mode 100644 src/cmd/go/testdata/script/mod_insecure_issue63845.txt
|
||||
|
||||
diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go
|
||||
index 91485f6f74..a890dc87c5 100644
|
||||
--- a/src/cmd/go/internal/vcs/vcs.go
|
||||
+++ b/src/cmd/go/internal/vcs/vcs.go
|
||||
@@ -892,19 +892,32 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
|
||||
if !srv.schemelessRepo {
|
||||
repoURL = match["repo"]
|
||||
} else {
|
||||
- scheme := vcs.Scheme[0] // default to first scheme
|
||||
repo := match["repo"]
|
||||
- if vcs.PingCmd != "" {
|
||||
- // If we know how to test schemes, scan to find one.
|
||||
+ scheme, err := func() (string, error) {
|
||||
for _, s := range vcs.Scheme {
|
||||
if security == web.SecureOnly && !vcs.isSecureScheme(s) {
|
||||
continue
|
||||
}
|
||||
- if vcs.Ping(s, repo) == nil {
|
||||
- scheme = s
|
||||
- break
|
||||
+
|
||||
+ // If we know how to ping URL schemes for this VCS,
|
||||
+ // check that this repo works.
|
||||
+ // Otherwise, default to the first scheme
|
||||
+ // that meets the requested security level.
|
||||
+ if vcs.PingCmd == "" {
|
||||
+ return s, nil
|
||||
+ }
|
||||
+ if err := vcs.Ping(s, repo); err == nil {
|
||||
+ return s, nil
|
||||
}
|
||||
}
|
||||
+ securityFrag := ""
|
||||
+ if security == web.SecureOnly {
|
||||
+ securityFrag = "secure "
|
||||
+ }
|
||||
+ return "", fmt.Errorf("no %sprotocol found for repository", securityFrag)
|
||||
+ }()
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
}
|
||||
repoURL = scheme + "://" + repo
|
||||
}
|
||||
diff --git a/src/cmd/go/testdata/script/mod_insecure_issue63845.txt b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt
|
||||
new file mode 100644
|
||||
index 0000000000..5fa6a4f12b
|
||||
--- /dev/null
|
||||
+++ b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt
|
||||
@@ -0,0 +1,28 @@
|
||||
+# Regression test for https://go.dev/issue/63845:
|
||||
+# If 'git ls-remote' fails for all secure protocols,
|
||||
+# we should fail instead of falling back to an arbitrary protocol.
|
||||
+#
|
||||
+# Note that this test does not use the local vcweb test server
|
||||
+# (vcs-test.golang.org), because the hook for redirecting to that
|
||||
+# server bypasses the "ping to determine protocol" logic
|
||||
+# in cmd/go/internal/vcs.
|
||||
+
|
||||
+[!net] skip
|
||||
+[!git] skip
|
||||
+[short] skip 'tries to access a nonexistent external Git repo'
|
||||
+
|
||||
+env GOPRIVATE=golang.org
|
||||
+env CURLOPT_TIMEOUT_MS=100
|
||||
+env GIT_SSH_COMMAND=false
|
||||
+
|
||||
+! go get -x golang.org/nonexist.git@latest
|
||||
+stderr '^git ls-remote https://golang.org/nonexist$'
|
||||
+stderr '^git ls-remote git\+ssh://golang.org/nonexist'
|
||||
+stderr '^git ls-remote ssh://golang.org/nonexist$'
|
||||
+! stderr 'git://'
|
||||
+stderr '^go: golang.org/nonexist.git@latest: no secure protocol found for repository$'
|
||||
+
|
||||
+-- go.mod --
|
||||
+module example
|
||||
+
|
||||
+go 1.19
|
||||
--
|
||||
2.33.0
|
||||
|
||||
43
0056-fix-test-error-about-mod_insecure_issue63845.patch
Normal file
43
0056-fix-test-error-about-mod_insecure_issue63845.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From 2a04aee674284f178b179f738a23a6ed3dd50b8c Mon Sep 17 00:00:00 2001
|
||||
From: wangshuo <wangshuo@kylinos.cn>
|
||||
Date: Fri, 22 Dec 2023 07:54:36 +0800
|
||||
Subject: [PATCH] fix test error about mod_insecure_issue63845
|
||||
|
||||
---
|
||||
.../go/testdata/script/mod_insecure_issue63845.txt | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/cmd/go/testdata/script/mod_insecure_issue63845.txt b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt
|
||||
index 5fa6a4f..a2d5c07 100644
|
||||
--- a/src/cmd/go/testdata/script/mod_insecure_issue63845.txt
|
||||
+++ b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt
|
||||
@@ -8,19 +8,19 @@
|
||||
# in cmd/go/internal/vcs.
|
||||
|
||||
[!net] skip
|
||||
-[!git] skip
|
||||
+[!exec:git] skip
|
||||
[short] skip 'tries to access a nonexistent external Git repo'
|
||||
|
||||
-env GOPRIVATE=golang.org
|
||||
+env GOPRIVATE=goproxy.cn
|
||||
env CURLOPT_TIMEOUT_MS=100
|
||||
env GIT_SSH_COMMAND=false
|
||||
|
||||
-! go get -x golang.org/nonexist.git@latest
|
||||
-stderr '^git ls-remote https://golang.org/nonexist$'
|
||||
-stderr '^git ls-remote git\+ssh://golang.org/nonexist'
|
||||
-stderr '^git ls-remote ssh://golang.org/nonexist$'
|
||||
+! go get -x goproxy.cn/nonexist.git@latest
|
||||
+stderr '^git ls-remote https://goproxy.cn/nonexist$'
|
||||
+stderr '^git ls-remote git\+ssh://goproxy.cn/nonexist'
|
||||
+stderr '^git ls-remote ssh://goproxy.cn/nonexist$'
|
||||
! stderr 'git://'
|
||||
-stderr '^go: golang.org/nonexist.git@latest: no secure protocol found for repository$'
|
||||
+stderr '^go get goproxy.cn/nonexist.git@latest: no secure protocol found for repository$'
|
||||
|
||||
-- go.mod --
|
||||
module example
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
From 1b914ecf43e875a5134e7c36a5042822b7f890f8 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Thu, 18 Jan 2024 12:51:13 -0800
|
||||
Subject: [PATCH 1/4] [release-branch.go1.21] crypto/x509: make sure pub key is
|
||||
non-nil before interface conversion
|
||||
|
||||
alreadyInChain assumes all keys fit a interface which contains the
|
||||
Equal method (which they do), but this ignores that certificates may
|
||||
have a nil key when PublicKeyAlgorithm is UnknownPublicKeyAlgorithm. In
|
||||
this case alreadyInChain panics.
|
||||
|
||||
Check that the key is non-nil as part of considerCandidate (we are never
|
||||
going to build a chain containing UnknownPublicKeyAlgorithm anyway).
|
||||
|
||||
For #65390
|
||||
Fixes #65392
|
||||
Fixes CVE-2024-24783
|
||||
|
||||
Change-Id: Ibdccc0a487e3368b6812be35daad2512220243f3
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2137282
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173774
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Carlos Amedee <amedee@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/569238
|
||||
Auto-Submit: Michael Knyszek <mknyszek@google.com>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
---
|
||||
src/crypto/x509/verify.go | 4 ++++
|
||||
src/crypto/x509/verify_test.go | 19 +++++++++++++++++++
|
||||
2 files changed, 23 insertions(+)
|
||||
|
||||
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
|
||||
index 9ef11466a47..b808f7d96b9 100644
|
||||
--- a/src/crypto/x509/verify.go
|
||||
+++ b/src/crypto/x509/verify.go
|
||||
@@ -819,6 +819,10 @@ func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, curre
|
||||
)
|
||||
|
||||
considerCandidate := func(certType int, candidate *Certificate) {
|
||||
+ if candidate.PublicKey == nil {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
for _, cert := range currentChain {
|
||||
if cert.Equal(candidate) {
|
||||
return
|
||||
diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
|
||||
index 9954a670da0..9da39ca94f6 100644
|
||||
--- a/src/crypto/x509/verify_test.go
|
||||
+++ b/src/crypto/x509/verify_test.go
|
||||
@@ -1968,3 +1968,22 @@ func TestSystemRootsErrorUnwrap(t *testing.T) {
|
||||
t.Error("errors.Is failed, wanted success")
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestVerifyNilPubKey(t *testing.T) {
|
||||
+ c := &Certificate{
|
||||
+ RawIssuer: []byte{1, 2, 3},
|
||||
+ AuthorityKeyId: []byte{1, 2, 3},
|
||||
+ }
|
||||
+ opts := &VerifyOptions{}
|
||||
+ opts.Roots = NewCertPool()
|
||||
+ r := &Certificate{
|
||||
+ RawSubject: []byte{1, 2, 3},
|
||||
+ SubjectKeyId: []byte{1, 2, 3},
|
||||
+ }
|
||||
+ opts.Roots.AddCert(r)
|
||||
+
|
||||
+ _, err := c.buildChains(nil, []*Certificate{r}, nil, opts)
|
||||
+ if _, ok := err.(UnknownAuthorityError); !ok {
|
||||
+ t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{})
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
193
0058-release-branch.go1.21-html-template-escape-additiona.patch
Normal file
193
0058-release-branch.go1.21-html-template-escape-additiona.patch
Normal file
@ -0,0 +1,193 @@
|
||||
From d4653b9d8b610a6aaad084a4bffd6eccea993f6f Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <roland@golang.org>
|
||||
Date: Wed, 14 Feb 2024 17:18:36 -0800
|
||||
Subject: [PATCH 2/4] [release-branch.go1.21] html/template: escape additional
|
||||
tokens in MarshalJSON errors
|
||||
|
||||
Escape "</script" and "<!--" in errors returned from MarshalJSON errors
|
||||
when attempting to marshal types in script blocks. This prevents any
|
||||
user controlled content from prematurely terminating the script block.
|
||||
|
||||
Updates #65697
|
||||
Fixes #65968
|
||||
|
||||
Change-Id: Icf0e26c54ea7d9c1deed0bff11b6506c99ddef1b
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/564196
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
(cherry picked from commit ccbc725f2d678255df1bd326fa511a492aa3a0aa)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/567515
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
---
|
||||
src/html/template/js.go | 22 ++++++++-
|
||||
src/html/template/js_test.go | 96 ++++++++++++++++++++----------------
|
||||
2 files changed, 74 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/src/html/template/js.go b/src/html/template/js.go
|
||||
index 35994f076eb..4d3b25d088c 100644
|
||||
--- a/src/html/template/js.go
|
||||
+++ b/src/html/template/js.go
|
||||
@@ -171,13 +171,31 @@ func jsValEscaper(args ...interface{}) string {
|
||||
// cyclic data. This may be an unacceptable DoS risk.
|
||||
b, err := json.Marshal(a)
|
||||
if err != nil {
|
||||
- // Put a space before comment so that if it is flush against
|
||||
+ // While the standard JSON marshaller does not include user controlled
|
||||
+ // information in the error message, if a type has a MarshalJSON method,
|
||||
+ // the content of the error message is not guaranteed. Since we insert
|
||||
+ // the error into the template, as part of a comment, we attempt to
|
||||
+ // prevent the error from either terminating the comment, or the script
|
||||
+ // block itself.
|
||||
+ //
|
||||
+ // In particular we:
|
||||
+ // * replace "*/" comment end tokens with "* /", which does not
|
||||
+ // terminate the comment
|
||||
+ // * replace "</script" with "\x3C/script", and "<!--" with
|
||||
+ // "\x3C!--", which prevents confusing script block termination
|
||||
+ // semantics
|
||||
+ //
|
||||
+ // We also put a space before the comment so that if it is flush against
|
||||
// a division operator it is not turned into a line comment:
|
||||
// x/{{y}}
|
||||
// turning into
|
||||
// x//* error marshaling y:
|
||||
// second line of error message */null
|
||||
- return fmt.Sprintf(" /* %s */null ", strings.ReplaceAll(err.Error(), "*/", "* /"))
|
||||
+ errStr := err.Error()
|
||||
+ errStr = strings.ReplaceAll(errStr, "*/", "* /")
|
||||
+ errStr = strings.ReplaceAll(errStr, "</script", `\x3C/script`)
|
||||
+ errStr = strings.ReplaceAll(errStr, "<!--", `\x3C!--`)
|
||||
+ return fmt.Sprintf(" /* %s */null ", errStr)
|
||||
}
|
||||
|
||||
// TODO: maybe post-process output to prevent it from containing
|
||||
diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
|
||||
index de9ef284106..0ad7b49d646 100644
|
||||
--- a/src/html/template/js_test.go
|
||||
+++ b/src/html/template/js_test.go
|
||||
@@ -6,6 +6,7 @@ package template
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
+ "errors"
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -104,61 +105,72 @@ func TestNextJsCtx(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+type jsonErrType struct{}
|
||||
+
|
||||
+func (e *jsonErrType) MarshalJSON() ([]byte, error) {
|
||||
+ return nil, errors.New("beep */ boop </script blip <!--")
|
||||
+}
|
||||
+
|
||||
func TestJSValEscaper(t *testing.T) {
|
||||
tests := []struct {
|
||||
- x interface{}
|
||||
- js string
|
||||
+ x any
|
||||
+ js string
|
||||
+ skipNest bool
|
||||
}{
|
||||
- {int(42), " 42 "},
|
||||
- {uint(42), " 42 "},
|
||||
- {int16(42), " 42 "},
|
||||
- {uint16(42), " 42 "},
|
||||
- {int32(-42), " -42 "},
|
||||
- {uint32(42), " 42 "},
|
||||
- {int16(-42), " -42 "},
|
||||
- {uint16(42), " 42 "},
|
||||
- {int64(-42), " -42 "},
|
||||
- {uint64(42), " 42 "},
|
||||
- {uint64(1) << 53, " 9007199254740992 "},
|
||||
+ {int(42), " 42 ", false},
|
||||
+ {uint(42), " 42 ", false},
|
||||
+ {int16(42), " 42 ", false},
|
||||
+ {uint16(42), " 42 ", false},
|
||||
+ {int32(-42), " -42 ", false},
|
||||
+ {uint32(42), " 42 ", false},
|
||||
+ {int16(-42), " -42 ", false},
|
||||
+ {uint16(42), " 42 ", false},
|
||||
+ {int64(-42), " -42 ", false},
|
||||
+ {uint64(42), " 42 ", false},
|
||||
+ {uint64(1) << 53, " 9007199254740992 ", false},
|
||||
// ulp(1 << 53) > 1 so this loses precision in JS
|
||||
// but it is still a representable integer literal.
|
||||
- {uint64(1)<<53 + 1, " 9007199254740993 "},
|
||||
- {float32(1.0), " 1 "},
|
||||
- {float32(-1.0), " -1 "},
|
||||
- {float32(0.5), " 0.5 "},
|
||||
- {float32(-0.5), " -0.5 "},
|
||||
- {float32(1.0) / float32(256), " 0.00390625 "},
|
||||
- {float32(0), " 0 "},
|
||||
- {math.Copysign(0, -1), " -0 "},
|
||||
- {float64(1.0), " 1 "},
|
||||
- {float64(-1.0), " -1 "},
|
||||
- {float64(0.5), " 0.5 "},
|
||||
- {float64(-0.5), " -0.5 "},
|
||||
- {float64(0), " 0 "},
|
||||
- {math.Copysign(0, -1), " -0 "},
|
||||
- {"", `""`},
|
||||
- {"foo", `"foo"`},
|
||||
+ {uint64(1)<<53 + 1, " 9007199254740993 ", false},
|
||||
+ {float32(1.0), " 1 ", false},
|
||||
+ {float32(-1.0), " -1 ", false},
|
||||
+ {float32(0.5), " 0.5 ", false},
|
||||
+ {float32(-0.5), " -0.5 ", false},
|
||||
+ {float32(1.0) / float32(256), " 0.00390625 ", false},
|
||||
+ {float32(0), " 0 ", false},
|
||||
+ {math.Copysign(0, -1), " -0 ", false},
|
||||
+ {float64(1.0), " 1 ", false},
|
||||
+ {float64(-1.0), " -1 ", false},
|
||||
+ {float64(0.5), " 0.5 ", false},
|
||||
+ {float64(-0.5), " -0.5 ", false},
|
||||
+ {float64(0), " 0 ", false},
|
||||
+ {math.Copysign(0, -1), " -0 ", false},
|
||||
+ {"", `""`, false},
|
||||
+ {"foo", `"foo"`, false},
|
||||
// Newlines.
|
||||
- {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
|
||||
+ {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`, false},
|
||||
// "\v" == "v" on IE 6 so use "\u000b" instead.
|
||||
- {"\t\x0b", `"\t\u000b"`},
|
||||
- {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
|
||||
- {[]interface{}{}, "[]"},
|
||||
- {[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
|
||||
- {[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`},
|
||||
- {"<!--", `"\u003c!--"`},
|
||||
- {"-->", `"--\u003e"`},
|
||||
- {"<![CDATA[", `"\u003c![CDATA["`},
|
||||
- {"]]>", `"]]\u003e"`},
|
||||
- {"</script", `"\u003c/script"`},
|
||||
- {"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
|
||||
- {nil, " null "},
|
||||
+ {"\t\x0b", `"\t\u000b"`, false},
|
||||
+ {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`, false},
|
||||
+ {[]any{}, "[]", false},
|
||||
+ {[]any{42, "foo", nil}, `[42,"foo",null]`, false},
|
||||
+ {[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`, false},
|
||||
+ {"<!--", `"\u003c!--"`, false},
|
||||
+ {"-->", `"--\u003e"`, false},
|
||||
+ {"<![CDATA[", `"\u003c![CDATA["`, false},
|
||||
+ {"]]>", `"]]\u003e"`, false},
|
||||
+ {"</script", `"\u003c/script"`, false},
|
||||
+ {"\U0001D11E", "\"\U0001D11E\"", false}, // or "\uD834\uDD1E"
|
||||
+ {nil, " null ", false},
|
||||
+ {&jsonErrType{}, " /* json: error calling MarshalJSON for type *template.jsonErrType: beep * / boop \\x3C/script blip \\x3C!-- */null ", true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if js := jsValEscaper(test.x); js != test.js {
|
||||
t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js)
|
||||
}
|
||||
+ if test.skipNest {
|
||||
+ continue
|
||||
+ }
|
||||
// Make sure that escaping corner cases are not broken
|
||||
// by nesting.
|
||||
a := []interface{}{test.x}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
267
0059-release-branch.go1.21-net-textproto-mime-multipart-a.patch
Normal file
267
0059-release-branch.go1.21-net-textproto-mime-multipart-a.patch
Normal file
@ -0,0 +1,267 @@
|
||||
From 3229bfd59fb630770f85dc474e70282707a4699d Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Tue, 16 Jan 2024 15:37:52 -0800
|
||||
Subject: [PATCH 3/4] [release-branch.go1.21] net/textproto, mime/multipart:
|
||||
avoid unbounded read in MIME header
|
||||
|
||||
mime/multipart.Reader.ReadForm allows specifying the maximum amount
|
||||
of memory that will be consumed by the form. While this limit is
|
||||
correctly applied to the parsed form data structure, it was not
|
||||
being applied to individual header lines in a form.
|
||||
|
||||
For example, when presented with a form containing a header line
|
||||
that never ends, ReadForm will continue to read the line until it
|
||||
runs out of memory.
|
||||
|
||||
Limit the amount of data consumed when reading a header.
|
||||
|
||||
Fixes CVE-2023-45290
|
||||
Fixes #65389
|
||||
For #65383
|
||||
|
||||
Change-Id: I7f9264d25752009e95f6b2c80e3d76aaf321d658
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2134435
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173776
|
||||
Reviewed-by: Carlos Amedee <amedee@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/569240
|
||||
Auto-Submit: Michael Knyszek <mknyszek@google.com>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
---
|
||||
src/mime/multipart/formdata_test.go | 42 +++++++++++++++++++++++++
|
||||
src/net/textproto/reader.go | 48 ++++++++++++++++++++---------
|
||||
src/net/textproto/reader_test.go | 12 ++++++++
|
||||
3 files changed, 87 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
|
||||
index c78eeb7a12b..f729da69547 100644
|
||||
--- a/src/mime/multipart/formdata_test.go
|
||||
+++ b/src/mime/multipart/formdata_test.go
|
||||
@@ -421,6 +421,48 @@ func TestReadFormLimits(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+func TestReadFormEndlessHeaderLine(t *testing.T) {
|
||||
+ for _, test := range []struct {
|
||||
+ name string
|
||||
+ prefix string
|
||||
+ }{{
|
||||
+ name: "name",
|
||||
+ prefix: "X-",
|
||||
+ }, {
|
||||
+ name: "value",
|
||||
+ prefix: "X-Header: ",
|
||||
+ }, {
|
||||
+ name: "continuation",
|
||||
+ prefix: "X-Header: foo\r\n ",
|
||||
+ }} {
|
||||
+ t.Run(test.name, func(t *testing.T) {
|
||||
+ const eol = "\r\n"
|
||||
+ s := `--boundary` + eol
|
||||
+ s += `Content-Disposition: form-data; name="a"` + eol
|
||||
+ s += `Content-Type: text/plain` + eol
|
||||
+ s += test.prefix
|
||||
+ fr := io.MultiReader(
|
||||
+ strings.NewReader(s),
|
||||
+ neverendingReader('X'),
|
||||
+ )
|
||||
+ r := NewReader(fr, "boundary")
|
||||
+ _, err := r.ReadForm(1 << 20)
|
||||
+ if err != ErrMessageTooLarge {
|
||||
+ t.Fatalf("ReadForm(1 << 20): %v, want ErrMessageTooLarge", err)
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+type neverendingReader byte
|
||||
+
|
||||
+func (r neverendingReader) Read(p []byte) (n int, err error) {
|
||||
+ for i := range p {
|
||||
+ p[i] = byte(r)
|
||||
+ }
|
||||
+ return len(p), nil
|
||||
+}
|
||||
+
|
||||
func BenchmarkReadForm(b *testing.B) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
|
||||
index 4299608d5ae..24d5e10c137 100644
|
||||
--- a/src/net/textproto/reader.go
|
||||
+++ b/src/net/textproto/reader.go
|
||||
@@ -16,6 +16,10 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
+// TODO: This should be a distinguishable error (ErrMessageTooLarge)
|
||||
+// to allow mime/multipart to detect it.
|
||||
+var errMessageTooLarge = errors.New("message too large")
|
||||
+
|
||||
// A Reader implements convenience methods for reading requests
|
||||
// or responses from a text protocol network connection.
|
||||
type Reader struct {
|
||||
@@ -37,13 +41,13 @@ func NewReader(r *bufio.Reader) *Reader {
|
||||
// ReadLine reads a single line from r,
|
||||
// eliding the final \n or \r\n from the returned string.
|
||||
func (r *Reader) ReadLine() (string, error) {
|
||||
- line, err := r.readLineSlice()
|
||||
+ line, err := r.readLineSlice(-1)
|
||||
return string(line), err
|
||||
}
|
||||
|
||||
// ReadLineBytes is like ReadLine but returns a []byte instead of a string.
|
||||
func (r *Reader) ReadLineBytes() ([]byte, error) {
|
||||
- line, err := r.readLineSlice()
|
||||
+ line, err := r.readLineSlice(-1)
|
||||
if line != nil {
|
||||
buf := make([]byte, len(line))
|
||||
copy(buf, line)
|
||||
@@ -52,7 +56,10 @@ func (r *Reader) ReadLineBytes() ([]byte, error) {
|
||||
return line, err
|
||||
}
|
||||
|
||||
-func (r *Reader) readLineSlice() ([]byte, error) {
|
||||
+// readLineSlice reads a single line from r,
|
||||
+// up to lim bytes long (or unlimited if lim is less than 0),
|
||||
+// eliding the final \r or \r\n from the returned string.
|
||||
+func (r *Reader) readLineSlice(lim int64) ([]byte, error) {
|
||||
r.closeDot()
|
||||
var line []byte
|
||||
for {
|
||||
@@ -60,6 +67,9 @@ func (r *Reader) readLineSlice() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
+ if lim >= 0 && int64(len(line))+int64(len(l)) > lim {
|
||||
+ return nil, errMessageTooLarge
|
||||
+ }
|
||||
// Avoid the copy if the first call produced a full line.
|
||||
if line == nil && !more {
|
||||
return l, nil
|
||||
@@ -92,7 +102,7 @@ func (r *Reader) readLineSlice() ([]byte, error) {
|
||||
// Empty lines are never continued.
|
||||
//
|
||||
func (r *Reader) ReadContinuedLine() (string, error) {
|
||||
- line, err := r.readContinuedLineSlice(noValidation)
|
||||
+ line, err := r.readContinuedLineSlice(-1, noValidation)
|
||||
return string(line), err
|
||||
}
|
||||
|
||||
@@ -113,7 +123,7 @@ func trim(s []byte) []byte {
|
||||
// ReadContinuedLineBytes is like ReadContinuedLine but
|
||||
// returns a []byte instead of a string.
|
||||
func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
|
||||
- line, err := r.readContinuedLineSlice(noValidation)
|
||||
+ line, err := r.readContinuedLineSlice(-1, noValidation)
|
||||
if line != nil {
|
||||
buf := make([]byte, len(line))
|
||||
copy(buf, line)
|
||||
@@ -126,13 +136,14 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
|
||||
// returning a byte slice with all lines. The validateFirstLine function
|
||||
// is run on the first read line, and if it returns an error then this
|
||||
// error is returned from readContinuedLineSlice.
|
||||
-func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) {
|
||||
+// It reads up to lim bytes of data (or unlimited if lim is less than 0).
|
||||
+func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
|
||||
if validateFirstLine == nil {
|
||||
return nil, fmt.Errorf("missing validateFirstLine func")
|
||||
}
|
||||
|
||||
// Read the first line.
|
||||
- line, err := r.readLineSlice()
|
||||
+ line, err := r.readLineSlice(lim)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -160,13 +171,21 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([
|
||||
// copy the slice into buf.
|
||||
r.buf = append(r.buf[:0], trim(line)...)
|
||||
|
||||
+ if lim < 0 {
|
||||
+ lim = math.MaxInt64
|
||||
+ }
|
||||
+ lim -= int64(len(r.buf))
|
||||
+
|
||||
// Read continuation lines.
|
||||
for r.skipSpace() > 0 {
|
||||
- line, err := r.readLineSlice()
|
||||
+ r.buf = append(r.buf, ' ')
|
||||
+ if int64(len(r.buf)) >= lim {
|
||||
+ return nil, errMessageTooLarge
|
||||
+ }
|
||||
+ line, err := r.readLineSlice(lim - int64(len(r.buf)))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
- r.buf = append(r.buf, ' ')
|
||||
r.buf = append(r.buf, trim(line)...)
|
||||
}
|
||||
return r.buf, nil
|
||||
@@ -511,7 +530,8 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
|
||||
|
||||
// The first line cannot start with a leading space.
|
||||
if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
|
||||
- line, err := r.readLineSlice()
|
||||
+ const errorLimit = 80 // arbitrary limit on how much of the line we'll quote
|
||||
+ line, err := r.readLineSlice(errorLimit)
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
@@ -519,7 +539,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
|
||||
}
|
||||
|
||||
for {
|
||||
- kv, err := r.readContinuedLineSlice(mustHaveFieldNameColon)
|
||||
+ kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon)
|
||||
if len(kv) == 0 {
|
||||
return m, err
|
||||
}
|
||||
@@ -540,7 +560,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
|
||||
|
||||
maxHeaders--
|
||||
if maxHeaders < 0 {
|
||||
- return nil, errors.New("message too large")
|
||||
+ return nil, errMessageTooLarge
|
||||
}
|
||||
|
||||
// Skip initial spaces in value.
|
||||
@@ -557,9 +577,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
|
||||
}
|
||||
maxMemory -= int64(len(value))
|
||||
if maxMemory < 0 {
|
||||
- // TODO: This should be a distinguishable error (ErrMessageTooLarge)
|
||||
- // to allow mime/multipart to detect it.
|
||||
- return m, errors.New("message too large")
|
||||
+ return m, errMessageTooLarge
|
||||
}
|
||||
if vv == nil && len(strs) > 0 {
|
||||
// More than likely this will be a single-element key.
|
||||
diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
|
||||
index 3ae0de13530..db1ed91bd51 100644
|
||||
--- a/src/net/textproto/reader_test.go
|
||||
+++ b/src/net/textproto/reader_test.go
|
||||
@@ -34,6 +34,18 @@ func TestReadLine(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+func TestReadLineLongLine(t *testing.T) {
|
||||
+ line := strings.Repeat("12345", 10000)
|
||||
+ r := reader(line + "\r\n")
|
||||
+ s, err := r.ReadLine()
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("Line 1: %v", err)
|
||||
+ }
|
||||
+ if s != line {
|
||||
+ t.Fatalf("%v-byte line does not match expected %v-byte line", len(s), len(line))
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func TestReadContinuedLine(t *testing.T) {
|
||||
r := reader("line1\nline\n 2\nline3\n")
|
||||
s, err := r.ReadContinuedLine()
|
||||
--
|
||||
2.33.0
|
||||
|
||||
117
0060-release-branch.go1.21-net-http-net-http-cookiejar-av.patch
Normal file
117
0060-release-branch.go1.21-net-http-net-http-cookiejar-av.patch
Normal file
@ -0,0 +1,117 @@
|
||||
From 3d8f3225528f917733569e0ea168581fe8bc1bcc Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Thu, 11 Jan 2024 11:31:57 -0800
|
||||
Subject: [PATCH 4/4] [release-branch.go1.21] net/http, net/http/cookiejar:
|
||||
avoid subdomain matches on IPv6 zones
|
||||
|
||||
When deciding whether to forward cookies or sensitive headers
|
||||
across a redirect, do not attempt to interpret an IPv6 address
|
||||
as a domain name.
|
||||
|
||||
Avoids a case where a maliciously-crafted redirect to an
|
||||
IPv6 address with a scoped addressing zone could be
|
||||
misinterpreted as a within-domain redirect. For example,
|
||||
we could interpret "::1%.www.example.com" as a subdomain
|
||||
of "www.example.com".
|
||||
|
||||
Thanks to Juho Nurminen of Mattermost for reporting this issue.
|
||||
|
||||
Fixes CVE-2023-45289
|
||||
Fixes #65385
|
||||
For #65065
|
||||
|
||||
Change-Id: I8f463f59f0e700c8a18733d2b264a8bcb3a19599
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2131938
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173775
|
||||
Reviewed-by: Carlos Amedee <amedee@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/569239
|
||||
Reviewed-by: Carlos Amedee <carlos@golang.org>
|
||||
Auto-Submit: Michael Knyszek <mknyszek@google.com>
|
||||
TryBot-Bypass: Michael Knyszek <mknyszek@google.com>
|
||||
---
|
||||
src/net/http/client.go | 6 ++++++
|
||||
src/net/http/client_test.go | 1 +
|
||||
src/net/http/cookiejar/jar.go | 7 +++++++
|
||||
src/net/http/cookiejar/jar_test.go | 10 ++++++++++
|
||||
4 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/src/net/http/client.go b/src/net/http/client.go
|
||||
index 4d380c65db9..33a062aa922 100644
|
||||
--- a/src/net/http/client.go
|
||||
+++ b/src/net/http/client.go
|
||||
@@ -1016,6 +1016,12 @@ func isDomainOrSubdomain(sub, parent string) bool {
|
||||
if sub == parent {
|
||||
return true
|
||||
}
|
||||
+ // If sub contains a :, it's probably an IPv6 address (and is definitely not a hostname).
|
||||
+ // Don't check the suffix in this case, to avoid matching the contents of a IPv6 zone.
|
||||
+ // For example, "::1%.www.example.com" is not a subdomain of "www.example.com".
|
||||
+ if strings.ContainsAny(sub, ":%") {
|
||||
+ return false
|
||||
+ }
|
||||
// If sub is "foo.example.com" and parent is "example.com",
|
||||
// that means sub must end in "."+parent.
|
||||
// Do it without allocating.
|
||||
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
|
||||
index 01d605c3519..ea71dd23644 100644
|
||||
--- a/src/net/http/client_test.go
|
||||
+++ b/src/net/http/client_test.go
|
||||
@@ -1702,6 +1702,7 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) {
|
||||
{"cookie2", "http://foo.com/", "http://bar.com/", false},
|
||||
{"authorization", "http://foo.com/", "http://bar.com/", false},
|
||||
{"www-authenticate", "http://foo.com/", "http://bar.com/", false},
|
||||
+ {"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false},
|
||||
|
||||
// But subdomains should work:
|
||||
{"www-authenticate", "http://foo.com/", "http://foo.com/", true},
|
||||
diff --git a/src/net/http/cookiejar/jar.go b/src/net/http/cookiejar/jar.go
|
||||
index e6583da7fe6..f2cf9c2d8de 100644
|
||||
--- a/src/net/http/cookiejar/jar.go
|
||||
+++ b/src/net/http/cookiejar/jar.go
|
||||
@@ -362,6 +362,13 @@ func jarKey(host string, psl PublicSuffixList) string {
|
||||
|
||||
// isIP reports whether host is an IP address.
|
||||
func isIP(host string) bool {
|
||||
+ if strings.ContainsAny(host, ":%") {
|
||||
+ // Probable IPv6 address.
|
||||
+ // Hostnames can't contain : or %, so this is definitely not a valid host.
|
||||
+ // Treating it as an IP is the more conservative option, and avoids the risk
|
||||
+ // of interpeting ::1%.www.example.com as a subtomain of www.example.com.
|
||||
+ return true
|
||||
+ }
|
||||
return net.ParseIP(host) != nil
|
||||
}
|
||||
|
||||
diff --git a/src/net/http/cookiejar/jar_test.go b/src/net/http/cookiejar/jar_test.go
|
||||
index 47fb1abdaaf..fd8d40ed1b9 100644
|
||||
--- a/src/net/http/cookiejar/jar_test.go
|
||||
+++ b/src/net/http/cookiejar/jar_test.go
|
||||
@@ -251,6 +251,7 @@ var isIPTests = map[string]bool{
|
||||
"127.0.0.1": true,
|
||||
"1.2.3.4": true,
|
||||
"2001:4860:0:2001::68": true,
|
||||
+ "::1%zone": true,
|
||||
"example.com": false,
|
||||
"1.1.1.300": false,
|
||||
"www.foo.bar.net": false,
|
||||
@@ -613,6 +614,15 @@ var basicsTests = [...]jarTest{
|
||||
{"http://www.host.test:1234/", "a=1"},
|
||||
},
|
||||
},
|
||||
+ {
|
||||
+ "IPv6 zone is not treated as a host.",
|
||||
+ "https://example.com/",
|
||||
+ []string{"a=1"},
|
||||
+ "a=1",
|
||||
+ []query{
|
||||
+ {"https://[::1%25.example.com]:80/", ""},
|
||||
+ },
|
||||
+ },
|
||||
}
|
||||
|
||||
func TestBasics(t *testing.T) {
|
||||
--
|
||||
2.33.0
|
||||
|
||||
56
golang.spec
56
golang.spec
@ -63,7 +63,7 @@
|
||||
|
||||
Name: golang
|
||||
Version: 1.17.3
|
||||
Release: 21
|
||||
Release: 28
|
||||
Summary: The Go Programming Language
|
||||
License: BSD and Public Domain
|
||||
URL: https://golang.org/
|
||||
@ -198,6 +198,18 @@ Patch6045: 0045-Backport-cmd-go-enforce-flags-with-non-optional-argu.patch
|
||||
Patch6046: 0046-Backport-cmd-go-cmd-cgo-in-_cgo_flags-use-one-line-p.patch
|
||||
Patch6047: 0047-Backport-net-http-validate-Host-header-before-sendin.patch
|
||||
Patch6048: 0048-Backport-net-http-permit-requests-with-invalid-Host-headers.patch
|
||||
Patch6049: 0049-Backport-crypto-tls-restrict-RSA-keys-in-certificates-to-8192.patch
|
||||
Patch6050: 0050-Backport-html-template-support-HTML-like-comments-in.patch
|
||||
Patch6051: 0051-Backport-html-template-properly-handle-special-tags-.patch
|
||||
Patch6052: 0052-Backport-cmd-compile-use-absolute-file-name-in-isCgo.patch
|
||||
Patch6053: 0053-CVE-2023-39325-net-http-regenerate-h2_bundle.go.patch
|
||||
Patch6054: 0054-CVE-2023-39326-net-http-limit-chunked-data-overhead.patch
|
||||
Patch6055: 0055-CVE-2023-45285-cmd-go-internal-vcs-error-out-if-the-reques.patch
|
||||
Patch6056: 0056-fix-test-error-about-mod_insecure_issue63845.patch
|
||||
Patch6057: 0057-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch
|
||||
Patch6058: 0058-release-branch.go1.21-html-template-escape-additiona.patch
|
||||
Patch6059: 0059-release-branch.go1.21-net-textproto-mime-multipart-a.patch
|
||||
Patch6060: 0060-release-branch.go1.21-net-http-net-http-cookiejar-av.patch
|
||||
|
||||
ExclusiveArch: %{golang_arches}
|
||||
|
||||
@ -436,6 +448,48 @@ fi
|
||||
%files devel -f go-tests.list -f go-misc.list -f go-src.list
|
||||
|
||||
%changelog
|
||||
* Fri Mar 15 2024 hanchao <hanchao63@huawei.com> - 1.17.3-28
|
||||
- Type:CVE
|
||||
- CVE:CVE-2024-24783,CVE-2024-24785,CVE-2023-45290,CVE-2023-45289
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2024-24783,CVE-2024-24785,CVE-2023-45290,CVE-2023-45289
|
||||
|
||||
* Tue Jan 16 2024 wangshuo <wangshuo@kylinos.cn> - 1.17.3-27
|
||||
- Type:bugfix
|
||||
- ID:NA
|
||||
- SUG:NA
|
||||
- DESC:fix test error about mod_insecure_issue63845
|
||||
|
||||
* Fri Dec 15 2023 hanchao <hanchao63@huawei.com> - 1.17.3-26
|
||||
- Type:CVE
|
||||
- CVE:CVE-2023-39326,CVE-2023-45285
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2023-39326,CVE-2023-45285
|
||||
|
||||
* Mon Oct 23 2023 hanchao <hanchao63@huawei.com> - 1.17.3-25
|
||||
- Type:CVE
|
||||
- CVE:CVE-2023-39325
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2023-39325
|
||||
|
||||
* Fri Oct 13 2023 luoyujie <luoyujie5@huawei.com> - 1.17.3-24
|
||||
- Type:CVE
|
||||
- CVE:CVE-2023-39323
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2023-39323
|
||||
|
||||
* Mon Sep 25 2023 luoyujie <luoyujie5@huawei.com> - 1.17.3-23
|
||||
- Type:CVE
|
||||
- CVE:CVE-2023-39318,CVE-2023-39319
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2023-39318 and CVE-2023-39319
|
||||
|
||||
* Fri Aug 25 2023 luoyujie <luoyujie5@huawei.com> - 1.17.3-22
|
||||
- Type:CVE
|
||||
- CVE:CVE-2023-29409
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2023-29409
|
||||
|
||||
* Fri Aug 25 2023 sunchendong <sunchendong@xfusion.com> - 1.17.3-21
|
||||
- permit invalid host header for docker
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user