diff options
author | Anna Henningsen <anna@addaleax.net> | 2019-08-11 00:37:58 +0300 |
---|---|---|
committer | Beth Griggs <Bethany.Griggs@uk.ibm.com> | 2019-08-15 17:20:49 +0300 |
commit | 17357d37a9eba4ac1cbafe8628bf12cc900bc642 (patch) | |
tree | 71eb349b6622103f29adac082eb78d859670ccd2 /src | |
parent | 460f896c631f1be52b0ab6c9f30e0b66f601b2a1 (diff) |
http2: consider 0-length non-end DATA frames an error
This is intended to mitigate CVE-2019-9518.
Backport-PR-URL: https://github.com/nodejs/node/pull/29123
PR-URL: https://github.com/nodejs/node/pull/29122
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/node_http2.cc | 12 | ||||
-rw-r--r-- | src/node_http2.h | 2 | ||||
-rw-r--r-- | src/node_revert.h | 1 |
3 files changed, 10 insertions, 5 deletions
diff --git a/src/node_http2.cc b/src/node_http2.cc index e03366dd1a0..c513d286e75 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -980,8 +980,7 @@ int Http2Session::OnFrameReceive(nghttp2_session* handle, frame->hd.type); switch (frame->hd.type) { case NGHTTP2_DATA: - session->HandleDataFrame(frame); - break; + return session->HandleDataFrame(frame); case NGHTTP2_PUSH_PROMISE: // Intentional fall-through, handled just like headers frames case NGHTTP2_HEADERS: @@ -1398,13 +1397,18 @@ void Http2Session::HandlePriorityFrame(const nghttp2_frame* frame) { // Called by OnFrameReceived when a complete DATA frame has been received. // If we know that this was the last DATA frame (because the END_STREAM flag // is set), then we'll terminate the readable side of the StreamBase. -void Http2Session::HandleDataFrame(const nghttp2_frame* frame) { +int Http2Session::HandleDataFrame(const nghttp2_frame* frame) { int32_t id = GetFrameID(frame); Debug(this, "handling data frame for stream %d", id); Http2Stream* stream = FindStream(id); - if (!stream->IsDestroyed() && frame->hd.flags & NGHTTP2_FLAG_END_STREAM) + if (!stream->IsDestroyed() && frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { stream->EmitRead(UV_EOF); + } else if (frame->hd.length == 0 && + !IsReverted(SECURITY_REVERT_CVE_2019_9518)) { + return 1; // Consider 0-length frame without END_STREAM an error. + } + return 0; } diff --git a/src/node_http2.h b/src/node_http2.h index da2acbca2ca..6fb8e097517 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -889,7 +889,7 @@ class Http2Session : public AsyncWrap, public StreamListener { size_t maxPayloadLen); // Frame Handler - void HandleDataFrame(const nghttp2_frame* frame); + int HandleDataFrame(const nghttp2_frame* frame); void HandleGoawayFrame(const nghttp2_frame* frame); void HandleHeadersFrame(const nghttp2_frame* frame); void HandlePriorityFrame(const nghttp2_frame* frame); diff --git a/src/node_revert.h b/src/node_revert.h index 50ada582de4..9646588740a 100644 --- a/src/node_revert.h +++ b/src/node_revert.h @@ -18,6 +18,7 @@ namespace node { #define SECURITY_REVERSIONS(XX) \ XX(CVE_2019_9514, "CVE-2019-9514", "HTTP/2 Reset Flood") \ XX(CVE_2019_9516, "CVE-2019-9516", "HTTP/2 0-Length Headers Leak") \ + XX(CVE_2019_9518, "CVE-2019-9518", "HTTP/2 Empty DATA Frame Flooding") \ // XX(CVE_2016_PEND, "CVE-2016-PEND", "Vulnerability Title") // TODO(addaleax): Remove all of the above before Node.js 13 as the comment // at the start of the file indicates. |