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 @@
+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