Skip to content

Commit d3beb50

Browse files
jasnelltargos
authored andcommitted
deps: update nghttp2 to 1.41.0
Fixes: https://hackerone.com/reports/446662 CVE-ID: CVE-2020-11080 PR-URL: nodejs-private/node-private#204 Reviewed-By: Matteo Collina <[email protected]>
1 parent 656260b commit d3beb50

9 files changed

+128
-127
lines changed

deps/nghttp2/lib/CMakeLists.txt

-76
This file was deleted.

deps/nghttp2/lib/includes/nghttp2/nghttp2.h

+23
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,13 @@ typedef struct {
228228
*/
229229
#define NGHTTP2_CLIENT_MAGIC_LEN 24
230230

231+
/**
232+
* @macro
233+
*
234+
* The default max number of settings per SETTINGS frame
235+
*/
236+
#define NGHTTP2_DEFAULT_MAX_SETTINGS 32
237+
231238
/**
232239
* @enum
233240
*
@@ -398,6 +405,11 @@ typedef enum {
398405
* receives an other type of frame.
399406
*/
400407
NGHTTP2_ERR_SETTINGS_EXPECTED = -536,
408+
/**
409+
* When a local endpoint receives too many settings entries
410+
* in a single SETTINGS frame.
411+
*/
412+
NGHTTP2_ERR_TOO_MANY_SETTINGS = -537,
401413
/**
402414
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
403415
* under unexpected condition and processing was terminated (e.g.,
@@ -2659,6 +2671,17 @@ NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
26592671
NGHTTP2_EXTERN void nghttp2_option_set_max_outbound_ack(nghttp2_option *option,
26602672
size_t val);
26612673

2674+
/**
2675+
* @function
2676+
*
2677+
* This function sets the maximum number of SETTINGS entries per
2678+
* SETTINGS frame that will be accepted. If more than those entries
2679+
* are received, the peer is considered to be misbehaving and session
2680+
* will be closed. The default value is 32.
2681+
*/
2682+
NGHTTP2_EXTERN void nghttp2_option_set_max_settings(nghttp2_option *option,
2683+
size_t val);
2684+
26622685
/**
26632686
* @function
26642687
*

deps/nghttp2/lib/includes/nghttp2/nghttp2ver.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929
* @macro
3030
* Version number of the nghttp2 library release
3131
*/
32-
#define NGHTTP2_VERSION "1.40.0"
32+
#define NGHTTP2_VERSION "1.41.0"
3333

3434
/**
3535
* @macro
3636
* Numerical representation of the version number of the nghttp2 library
3737
* release. This is a 24 bit number with 8 bits for major number, 8 bits
3838
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
3939
*/
40-
#define NGHTTP2_VERSION_NUM 0x012800
40+
#define NGHTTP2_VERSION_NUM 0x012900
4141

4242
#endif /* NGHTTP2VER_H */

deps/nghttp2/lib/nghttp2_helper.c

+2
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,8 @@ const char *nghttp2_strerror(int error_code) {
334334
case NGHTTP2_ERR_FLOODED:
335335
return "Flooding was detected in this HTTP/2 session, and it must be "
336336
"closed";
337+
case NGHTTP2_ERR_TOO_MANY_SETTINGS:
338+
return "SETTINGS frame contained more than the maximum allowed entries";
337339
default:
338340
return "Unknown error code";
339341
}

deps/nghttp2/lib/nghttp2_option.c

+5
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,8 @@ void nghttp2_option_set_max_outbound_ack(nghttp2_option *option, size_t val) {
121121
option->opt_set_mask |= NGHTTP2_OPT_MAX_OUTBOUND_ACK;
122122
option->max_outbound_ack = val;
123123
}
124+
125+
void nghttp2_option_set_max_settings(nghttp2_option *option, size_t val) {
126+
option->opt_set_mask |= NGHTTP2_OPT_MAX_SETTINGS;
127+
option->max_settings = val;
128+
}

deps/nghttp2/lib/nghttp2_option.h

+5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ typedef enum {
6767
NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9,
6868
NGHTTP2_OPT_NO_CLOSED_STREAMS = 1 << 10,
6969
NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11,
70+
NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
7071
} nghttp2_option_flag;
7172

7273
/**
@@ -85,6 +86,10 @@ struct nghttp2_option {
8586
* NGHTTP2_OPT_MAX_OUTBOUND_ACK
8687
*/
8788
size_t max_outbound_ack;
89+
/**
90+
* NGHTTP2_OPT_MAX_SETTINGS
91+
*/
92+
size_t max_settings;
8893
/**
8994
* Bitwise OR of nghttp2_option_flag to determine that which fields
9095
* are specified.

deps/nghttp2/lib/nghttp2_session.c

+43-45
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ static int session_new(nghttp2_session **session_ptr,
458458

459459
(*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN;
460460
(*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM;
461+
(*session_ptr)->max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS;
461462

462463
if (option) {
463464
if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) &&
@@ -521,6 +522,11 @@ static int session_new(nghttp2_session **session_ptr,
521522
if (option->opt_set_mask & NGHTTP2_OPT_MAX_OUTBOUND_ACK) {
522523
(*session_ptr)->max_outbound_ack = option->max_outbound_ack;
523524
}
525+
526+
if ((option->opt_set_mask & NGHTTP2_OPT_MAX_SETTINGS) &&
527+
option->max_settings) {
528+
(*session_ptr)->max_settings = option->max_settings;
529+
}
524530
}
525531

526532
rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
@@ -2494,14 +2500,6 @@ static int session_update_stream_consumed_size(nghttp2_session *session,
24942500
static int session_update_connection_consumed_size(nghttp2_session *session,
24952501
size_t delta_size);
24962502

2497-
static int session_update_recv_connection_window_size(nghttp2_session *session,
2498-
size_t delta_size);
2499-
2500-
static int session_update_recv_stream_window_size(nghttp2_session *session,
2501-
nghttp2_stream *stream,
2502-
size_t delta_size,
2503-
int send_window_update);
2504-
25052503
/*
25062504
* Called after a frame is sent. This function runs
25072505
* on_frame_send_callback and handles stream closure upon END_STREAM
@@ -2735,7 +2733,7 @@ static int session_after_frame_sent1(nghttp2_session *session) {
27352733
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
27362734
rv = session_update_connection_consumed_size(session, 0);
27372735
} else {
2738-
rv = session_update_recv_connection_window_size(session, 0);
2736+
rv = nghttp2_session_update_recv_connection_window_size(session, 0);
27392737
}
27402738

27412739
if (nghttp2_is_fatal(rv)) {
@@ -2761,7 +2759,8 @@ static int session_after_frame_sent1(nghttp2_session *session) {
27612759
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
27622760
rv = session_update_stream_consumed_size(session, stream, 0);
27632761
} else {
2764-
rv = session_update_recv_stream_window_size(session, stream, 0, 1);
2762+
rv =
2763+
nghttp2_session_update_recv_stream_window_size(session, stream, 0, 1);
27652764
}
27662765

27672766
if (nghttp2_is_fatal(rv)) {
@@ -5019,22 +5018,10 @@ static int adjust_recv_window_size(int32_t *recv_window_size_ptr, size_t delta,
50195018
return 0;
50205019
}
50215020

5022-
/*
5023-
* Accumulates received bytes |delta_size| for stream-level flow
5024-
* control and decides whether to send WINDOW_UPDATE to that stream.
5025-
* If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set, WINDOW_UPDATE will not
5026-
* be sent.
5027-
*
5028-
* This function returns 0 if it succeeds, or one of the following
5029-
* negative error codes:
5030-
*
5031-
* NGHTTP2_ERR_NOMEM
5032-
* Out of memory.
5033-
*/
5034-
static int session_update_recv_stream_window_size(nghttp2_session *session,
5035-
nghttp2_stream *stream,
5036-
size_t delta_size,
5037-
int send_window_update) {
5021+
int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session,
5022+
nghttp2_stream *stream,
5023+
size_t delta_size,
5024+
int send_window_update) {
50385025
int rv;
50395026
rv = adjust_recv_window_size(&stream->recv_window_size, delta_size,
50405027
stream->local_window_size);
@@ -5063,20 +5050,8 @@ static int session_update_recv_stream_window_size(nghttp2_session *session,
50635050
return 0;
50645051
}
50655052

5066-
/*
5067-
* Accumulates received bytes |delta_size| for connection-level flow
5068-
* control and decides whether to send WINDOW_UPDATE to the
5069-
* connection. If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set,
5070-
* WINDOW_UPDATE will not be sent.
5071-
*
5072-
* This function returns 0 if it succeeds, or one of the following
5073-
* negative error codes:
5074-
*
5075-
* NGHTTP2_ERR_NOMEM
5076-
* Out of memory.
5077-
*/
5078-
static int session_update_recv_connection_window_size(nghttp2_session *session,
5079-
size_t delta_size) {
5053+
int nghttp2_session_update_recv_connection_window_size(nghttp2_session *session,
5054+
size_t delta_size) {
50805055
int rv;
50815056
rv = adjust_recv_window_size(&session->recv_window_size, delta_size,
50825057
session->local_window_size);
@@ -5678,6 +5653,12 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
56785653
break;
56795654
}
56805655

5656+
/* Check the settings flood counter early to be safe */
5657+
if (session->obq_flood_counter_ >= session->max_outbound_ack &&
5658+
!(iframe->frame.hd.flags & NGHTTP2_FLAG_ACK)) {
5659+
return NGHTTP2_ERR_FLOODED;
5660+
}
5661+
56815662
iframe->state = NGHTTP2_IB_READ_SETTINGS;
56825663

56835664
if (iframe->payloadleft) {
@@ -5688,6 +5669,16 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
56885669
iframe->max_niv =
56895670
iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
56905671

5672+
if (iframe->max_niv - 1 > session->max_settings) {
5673+
rv = nghttp2_session_terminate_session_with_reason(
5674+
session, NGHTTP2_ENHANCE_YOUR_CALM,
5675+
"SETTINGS: too many setting entries");
5676+
if (nghttp2_is_fatal(rv)) {
5677+
return rv;
5678+
}
5679+
return (ssize_t)inlen;
5680+
}
5681+
56915682
iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
56925683
iframe->max_niv);
56935684

@@ -6454,7 +6445,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
64546445
}
64556446

64566447
/* Pad Length field is subject to flow control */
6457-
rv = session_update_recv_connection_window_size(session, readlen);
6448+
rv = nghttp2_session_update_recv_connection_window_size(session, readlen);
64586449
if (nghttp2_is_fatal(rv)) {
64596450
return rv;
64606451
}
@@ -6477,7 +6468,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
64776468

64786469
stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
64796470
if (stream) {
6480-
rv = session_update_recv_stream_window_size(
6471+
rv = nghttp2_session_update_recv_stream_window_size(
64816472
session, stream, readlen,
64826473
iframe->payloadleft ||
64836474
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
@@ -6524,7 +6515,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
65246515
if (readlen > 0) {
65256516
ssize_t data_readlen;
65266517

6527-
rv = session_update_recv_connection_window_size(session, readlen);
6518+
rv = nghttp2_session_update_recv_connection_window_size(session,
6519+
readlen);
65286520
if (nghttp2_is_fatal(rv)) {
65296521
return rv;
65306522
}
@@ -6533,7 +6525,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
65336525
return (ssize_t)inlen;
65346526
}
65356527

6536-
rv = session_update_recv_stream_window_size(
6528+
rv = nghttp2_session_update_recv_stream_window_size(
65376529
session, stream, readlen,
65386530
iframe->payloadleft ||
65396531
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
@@ -6634,7 +6626,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
66346626
if (readlen > 0) {
66356627
/* Update connection-level flow control window for ignored
66366628
DATA frame too */
6637-
rv = session_update_recv_connection_window_size(session, readlen);
6629+
rv = nghttp2_session_update_recv_connection_window_size(session,
6630+
readlen);
66386631
if (nghttp2_is_fatal(rv)) {
66396632
return rv;
66406633
}
@@ -7454,6 +7447,11 @@ static int nghttp2_session_upgrade_internal(nghttp2_session *session,
74547447
if (settings_payloadlen % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
74557448
return NGHTTP2_ERR_INVALID_ARGUMENT;
74567449
}
7450+
/* SETTINGS frame contains too many settings */
7451+
if (settings_payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH
7452+
> session->max_settings) {
7453+
return NGHTTP2_ERR_TOO_MANY_SETTINGS;
7454+
}
74577455
rv = nghttp2_frame_unpack_settings_payload2(&iv, &niv, settings_payload,
74587456
settings_payloadlen, mem);
74597457
if (rv != 0) {

0 commit comments

Comments
 (0)