summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch')
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch101
1 files changed, 101 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch
new file mode 100644
index 0000000000..9c00d4ebb2
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch
@@ -0,0 +1,101 @@
1From b7a85e0003cedb1b48a1fd3ae5b746ec6330102e Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Wed, 7 Jul 2021 16:34:34 -0700
4Subject: [PATCH] net/http/httputil: close incoming ReverseProxy request body
5
6Reading from an incoming request body after the request handler aborts
7with a panic can cause a panic, becuse http.Server does not (contrary
8to its documentation) close the request body in this case.
9
10Always close the incoming request body in ReverseProxy.ServeHTTP to
11ensure that any in-flight outgoing requests using the body do not
12read from it.
13
14Updates #46866
15Fixes CVE-2021-36221
16
17Change-Id: I310df269200ad8732c5d9f1a2b00de68725831df
18Reviewed-on: https://go-review.googlesource.com/c/go/+/333191
19Trust: Damien Neil <dneil@google.com>
20Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
21Reviewed-by: Filippo Valsorda <filippo@golang.org>
22
23https://github.com/golang/go/commit/b7a85e0003cedb1b48a1fd3ae5b746ec6330102e
24CVE: CVE-2021-36221
25Upstream-Status: Backport
26Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
27---
28 src/net/http/httputil/reverseproxy.go | 9 +++++
29 src/net/http/httputil/reverseproxy_test.go | 39 ++++++++++++++++++++++
30 2 files changed, 48 insertions(+)
31
32diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
33index 5d39955d62d15..8b63368386f43 100644
34--- a/src/net/http/httputil/reverseproxy.go
35+++ b/src/net/http/httputil/reverseproxy.go
36@@ -235,6 +235,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
37 if req.ContentLength == 0 {
38 outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
39 }
40+ if outreq.Body != nil {
41+ // Reading from the request body after returning from a handler is not
42+ // allowed, and the RoundTrip goroutine that reads the Body can outlive
43+ // this handler. This can lead to a crash if the handler panics (see
44+ // Issue 46866). Although calling Close doesn't guarantee there isn't
45+ // any Read in flight after the handle returns, in practice it's safe to
46+ // read after closing it.
47+ defer outreq.Body.Close()
48+ }
49 if outreq.Header == nil {
50 outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
51 }
52diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
53index 1898ed8b8afde..4b6ad77a29466 100644
54--- a/src/net/http/httputil/reverseproxy_test.go
55+++ b/src/net/http/httputil/reverseproxy_test.go
56@@ -1122,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) {
57 rproxy.ServeHTTP(httptest.NewRecorder(), req)
58 }
59
60+// Issue #46866: panic without closing incoming request body causes a panic
61+func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) {
62+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
63+ out := "this call was relayed by the reverse proxy"
64+ // Coerce a wrong content length to induce io.ErrUnexpectedEOF
65+ w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
66+ fmt.Fprintln(w, out)
67+ }))
68+ defer backend.Close()
69+ backendURL, err := url.Parse(backend.URL)
70+ if err != nil {
71+ t.Fatal(err)
72+ }
73+ proxyHandler := NewSingleHostReverseProxy(backendURL)
74+ proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
75+ frontend := httptest.NewServer(proxyHandler)
76+ defer frontend.Close()
77+ frontendClient := frontend.Client()
78+
79+ var wg sync.WaitGroup
80+ for i := 0; i < 2; i++ {
81+ wg.Add(1)
82+ go func() {
83+ defer wg.Done()
84+ for j := 0; j < 10; j++ {
85+ const reqLen = 6 * 1024 * 1024
86+ req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen})
87+ req.ContentLength = reqLen
88+ resp, _ := frontendClient.Transport.RoundTrip(req)
89+ if resp != nil {
90+ io.Copy(io.Discard, resp.Body)
91+ resp.Body.Close()
92+ }
93+ }
94+ }()
95+ }
96+ wg.Wait()
97+}
98+
99 func TestSelectFlushInterval(t *testing.T) {
100 tests := []struct {
101 name string