diff options
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.patch | 101 |
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 @@ +From b7a85e0003cedb1b48a1fd3ae5b746ec6330102e Mon Sep 17 00:00:00 2001 +From: Damien Neil <dneil@google.com> +Date: Wed, 7 Jul 2021 16:34:34 -0700 +Subject: [PATCH] net/http/httputil: close incoming ReverseProxy request body + +Reading from an incoming request body after the request handler aborts +with a panic can cause a panic, becuse http.Server does not (contrary +to its documentation) close the request body in this case. + +Always close the incoming request body in ReverseProxy.ServeHTTP to +ensure that any in-flight outgoing requests using the body do not +read from it. + +Updates #46866 +Fixes CVE-2021-36221 + +Change-Id: I310df269200ad8732c5d9f1a2b00de68725831df +Reviewed-on: https://go-review.googlesource.com/c/go/+/333191 +Trust: Damien Neil <dneil@google.com> +Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> +Reviewed-by: Filippo Valsorda <filippo@golang.org> + +https://github.com/golang/go/commit/b7a85e0003cedb1b48a1fd3ae5b746ec6330102e +CVE: CVE-2021-36221 +Upstream-Status: Backport +Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com> +--- + src/net/http/httputil/reverseproxy.go | 9 +++++ + src/net/http/httputil/reverseproxy_test.go | 39 ++++++++++++++++++++++ + 2 files changed, 48 insertions(+) + +diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go +index 5d39955d62d15..8b63368386f43 100644 +--- a/src/net/http/httputil/reverseproxy.go ++++ b/src/net/http/httputil/reverseproxy.go +@@ -235,6 +235,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + if req.ContentLength == 0 { + outreq.Body = nil // Issue 16036: nil Body for http.Transport retries + } ++ if outreq.Body != nil { ++ // Reading from the request body after returning from a handler is not ++ // allowed, and the RoundTrip goroutine that reads the Body can outlive ++ // this handler. This can lead to a crash if the handler panics (see ++ // Issue 46866). Although calling Close doesn't guarantee there isn't ++ // any Read in flight after the handle returns, in practice it's safe to ++ // read after closing it. ++ defer outreq.Body.Close() ++ } + if outreq.Header == nil { + outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate + } +diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go +index 1898ed8b8afde..4b6ad77a29466 100644 +--- a/src/net/http/httputil/reverseproxy_test.go ++++ b/src/net/http/httputil/reverseproxy_test.go +@@ -1122,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) { + rproxy.ServeHTTP(httptest.NewRecorder(), req) + } + ++// Issue #46866: panic without closing incoming request body causes a panic ++func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) { ++ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ out := "this call was relayed by the reverse proxy" ++ // Coerce a wrong content length to induce io.ErrUnexpectedEOF ++ w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2)) ++ fmt.Fprintln(w, out) ++ })) ++ defer backend.Close() ++ backendURL, err := url.Parse(backend.URL) ++ if err != nil { ++ t.Fatal(err) ++ } ++ proxyHandler := NewSingleHostReverseProxy(backendURL) ++ proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests ++ frontend := httptest.NewServer(proxyHandler) ++ defer frontend.Close() ++ frontendClient := frontend.Client() ++ ++ var wg sync.WaitGroup ++ for i := 0; i < 2; i++ { ++ wg.Add(1) ++ go func() { ++ defer wg.Done() ++ for j := 0; j < 10; j++ { ++ const reqLen = 6 * 1024 * 1024 ++ req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen}) ++ req.ContentLength = reqLen ++ resp, _ := frontendClient.Transport.RoundTrip(req) ++ if resp != nil { ++ io.Copy(io.Discard, resp.Body) ++ resp.Body.Close() ++ } ++ } ++ }() ++ } ++ wg.Wait() ++} ++ + func TestSelectFlushInterval(t *testing.T) { + tests := []struct { + name string |