Skip to content

Commit 05dada4

Browse files
addaleaxBethGriggs
authored andcommitted
http2: limit number of rejected stream openings
Limit the number of streams that are rejected upon creation. Since each such rejection is associated with an `NGHTTP2_ENHANCE_YOUR_CALM` error that should tell the peer to not open any more streams, continuing to open streams should be read as a sign of a misbehaving peer. The limit is currently set to 100 but could be changed or made configurable. This is intended to mitigate CVE-2019-9514. Backport-PR-URL: #29123 PR-URL: #29122 Reviewed-By: Rich Trott <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 7f11465 commit 05dada4

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

src/node_http2.cc

+8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "node_http2_state.h"
77
#include "node_internals.h"
88
#include "node_perf.h"
9+
#include "node_revert.h"
10+
#include "util-inl.h"
911

1012
#include <algorithm>
1113

@@ -921,11 +923,17 @@ int Http2Session::OnBeginHeadersCallback(nghttp2_session* handle,
921923
if (UNLIKELY(!session->CanAddStream() ||
922924
Http2Stream::New(session, id, frame->headers.cat) ==
923925
nullptr)) {
926+
if (session->rejected_stream_count_++ > 100 &&
927+
!IsReverted(SECURITY_REVERT_CVE_2019_9514)) {
928+
return NGHTTP2_ERR_CALLBACK_FAILURE;
929+
}
924930
// Too many concurrent streams being opened
925931
nghttp2_submit_rst_stream(**session, NGHTTP2_FLAG_NONE, id,
926932
NGHTTP2_ENHANCE_YOUR_CALM);
927933
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
928934
}
935+
936+
session->rejected_stream_count_ = 0;
929937
} else if (!stream->IsDestroyed()) {
930938
stream->StartHeaders(frame->headers.cat);
931939
}

src/node_http2.h

+5
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,11 @@ class Http2Session : public AsyncWrap, public StreamListener {
10171017
std::vector<nghttp2_stream_write> outgoing_buffers_;
10181018
std::vector<uint8_t> outgoing_storage_;
10191019
std::vector<int32_t> pending_rst_streams_;
1020+
// Count streams that have been rejected while being opened. Exceeding a fixed
1021+
// limit will result in the session being destroyed, as an indication of a
1022+
// misbehaving peer. This counter is reset once new streams are being
1023+
// accepted again.
1024+
int32_t rejected_stream_count_ = 0;
10201025

10211026
void CopyDataIntoOutgoing(const uint8_t* src, size_t src_length);
10221027
void ClearOutgoing(int status);

src/node_revert.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@
1515
**/
1616
namespace node {
1717

18-
#define SECURITY_REVERSIONS(XX)
18+
#define SECURITY_REVERSIONS(XX) \
19+
XX(CVE_2019_9514, "CVE-2019-9514", "HTTP/2 Reset Flood") \
1920
// XX(CVE_2016_PEND, "CVE-2016-PEND", "Vulnerability Title")
21+
// TODO(addaleax): Remove all of the above before Node.js 13 as the comment
22+
// at the start of the file indicates.
2023

2124
enum reversion {
2225
#define V(code, ...) SECURITY_REVERT_##code,

0 commit comments

Comments
 (0)