diff options
| author | Dmitri Shuralyov <dmitshur@golang.org> | 2024-04-03 15:52:28 -0400 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-04-05 22:18:39 +0000 |
| commit | 5d18f889276fec9fd478124a0691bd7d1bca37c1 (patch) | |
| tree | b40e2657e3c8ea94606cfda1db0ae6210551068d /src/net/http | |
| parent | d186dde81844badfa961f8af5044136dce8dc39e (diff) | |
| download | go-5d18f889276fec9fd478124a0691bd7d1bca37c1.tar.xz | |
all: update vendored golang.org/x/net to v0.23.0
Pull in CL 576155:
ba872109 http2: close connections when receiving too many headers
Fixes CVE-2023-45288.
Fixes #65051.
Change-Id: I3f4e3d565189b4ed552935fe1d96f94ebac86d48
Reviewed-on: https://go-review.googlesource.com/c/go/+/576295
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/net/http')
| -rw-r--r-- | src/net/http/h2_bundle.go | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index af839dd1bf..9285f90d9e 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -2972,6 +2972,7 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr if size > remainSize { hdec.SetEmitEnabled(false) mh.Truncated = true + remainSize = 0 return } remainSize -= size @@ -2984,6 +2985,36 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr var hc http2headersOrContinuation = hf for { frag := hc.HeaderBlockFragment() + + // Avoid parsing large amounts of headers that we will then discard. + // If the sender exceeds the max header list size by too much, + // skip parsing the fragment and close the connection. + // + // "Too much" is either any CONTINUATION frame after we've already + // exceeded the max header list size (in which case remainSize is 0), + // or a frame whose encoded size is more than twice the remaining + // header list bytes we're willing to accept. + if int64(len(frag)) > int64(2*remainSize) { + if http2VerboseLogs { + log.Printf("http2: header list too large") + } + // It would be nice to send a RST_STREAM before sending the GOAWAY, + // but the structure of the server's frame writer makes this difficult. + return nil, http2ConnectionError(http2ErrCodeProtocol) + } + + // Also close the connection after any CONTINUATION frame following an + // invalid header, since we stop tracking the size of the headers after + // an invalid one. + if invalid != nil { + if http2VerboseLogs { + log.Printf("http2: invalid header: %v", invalid) + } + // It would be nice to send a RST_STREAM before sending the GOAWAY, + // but the structure of the server's frame writer makes this difficult. + return nil, http2ConnectionError(http2ErrCodeProtocol) + } + if _, err := hdec.Write(frag); err != nil { return nil, http2ConnectionError(http2ErrCodeCompression) } @@ -7672,7 +7703,7 @@ type http2ClientConn struct { readerErr error // set before readerDone is closed idleTimeout time.Duration // or 0 for never - idleTimer *time.Timer + idleTimer http2timer mu sync.Mutex // guards following cond *sync.Cond // hold mu; broadcast on flow/closed changes @@ -8191,7 +8222,7 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool, hooks *http2t } if d := t.idleConnTimeout(); d != 0 { cc.idleTimeout = d - cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout) + cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout) } if http2VerboseLogs { t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr()) |
