From ba93baa74a52d57ae79313313ea990cc791ef50e Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Wed, 7 Jul 2021 16:34:34 -0700 Subject: [release-branch.go1.15] 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. Fixes #47473 Updates #46866 Fixes CVE-2021-36221 Change-Id: I310df269200ad8732c5d9f1a2b00de68725831df Reviewed-on: https://go-review.googlesource.com/c/go/+/333191 Trust: Damien Neil Reviewed-by: Brad Fitzpatrick Reviewed-by: Filippo Valsorda (cherry picked from commit b7a85e0003cedb1b48a1fd3ae5b746ec6330102e) Reviewed-on: https://go-review.googlesource.com/c/go/+/338550 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/http/httputil/reverseproxy.go | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/net/http/httputil/reverseproxy.go') diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index f49cefbb4f..68754cb088 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -234,6 +234,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 } -- cgit v1.2.3-54-g00ecf