CVE-2021-36221
authorGo Compiler Team <pkg-golang-devel@lists.alioth.debian.org>
Fri, 21 Jan 2022 18:45:18 +0000 (18:45 +0000)
committerSylvain Beucler <beuc@debian.org>
Fri, 21 Jan 2022 18:45:18 +0000 (18:45 +0000)
Origin: https://github.com/golang/go/commit/b7a85e0003cedb1b48a1fd3ae5b746ec6330102e
Reviewed-by: Sylvain Beucler <beuc@debian.org>
Last-Update: 2022-01-21

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>
Gbp-Pq: Name CVE-2021-36221.patch

src/net/http/httputil/reverseproxy.go

index 49c120afde12fc5f48054a2e7e94fe5887f4e92d..04b37a7362c7d0efe4ddd91fb5945cfcef07e500 100644 (file)
@@ -149,6 +149,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 
        outreq := new(http.Request)
        *outreq = *req // includes shallow copies of maps, but okay
+       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 closeNotifier, ok := rw.(http.CloseNotifier); ok {
                if requestCanceler, ok := transport.(requestCanceler); ok {