aboutsummaryrefslogtreecommitdiffstats
path: root/meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-2.patch')
-rw-r--r--meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-2.patch308
1 files changed, 308 insertions, 0 deletions
diff --git a/meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-2.patch b/meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-2.patch
new file mode 100644
index 0000000000..d3c57e9a80
--- /dev/null
+++ b/meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-2.patch
@@ -0,0 +1,308 @@
+From 336a98feb0d56b9ac54e12736b18785c27f75090 Mon Sep 17 00:00:00 2001
+From: James M Snell <jasnell@gmail.com>
+Date: Fri, 17 Apr 2020 16:53:51 -0700
+Subject: [PATCH] Implement max settings option
+
+CVE: CVE-2020-11080
+Upstream-Status: Backport [https://github.com/nghttp2/nghttp2/commit/336a98feb0d56b9ac54e12736b18785c27f75090.patch]
+Comment: No hunks refreshed
+Affects-version: < v1.41.0
+Signed-off-by: Rahul Taya <Rahul.Taya@kpit.com>
+---
+ doc/CMakeLists.txt | 1 +
+ doc/Makefile.am | 1 +
+ lib/includes/nghttp2/nghttp2.h | 23 +++++++++++++
+ lib/nghttp2_helper.c | 2 ++
+ lib/nghttp2_option.c | 5 +++
+ lib/nghttp2_option.h | 5 +++
+ lib/nghttp2_session.c | 21 ++++++++++++
+ lib/nghttp2_session.h | 2 ++
+ tests/main.c | 2 ++
+ tests/nghttp2_session_test.c | 61 ++++++++++++++++++++++++++++++++++
+ tests/nghttp2_session_test.h | 1 +
+ 11 files changed, 124 insertions(+)
+
+Index: nghttp2-1.40.0/doc/CMakeLists.txt
+===================================================================
+--- nghttp2-1.40.0.orig/doc/CMakeLists.txt
++++ nghttp2-1.40.0/doc/CMakeLists.txt
+@@ -42,6 +42,7 @@ set(APIDOCS
+ nghttp2_option_set_no_recv_client_magic.rst
+ nghttp2_option_set_peer_max_concurrent_streams.rst
+ nghttp2_option_set_user_recv_extension_type.rst
++ nghttp2_option_set_max_settings.rst
+ nghttp2_pack_settings_payload.rst
+ nghttp2_priority_spec_check_default.rst
+ nghttp2_priority_spec_default_init.rst
+Index: nghttp2-1.40.0/lib/includes/nghttp2/nghttp2.h
+===================================================================
+--- nghttp2-1.40.0.orig/lib/includes/nghttp2/nghttp2.h
++++ nghttp2-1.40.0/lib/includes/nghttp2/nghttp2.h
+@@ -229,6 +229,13 @@ typedef struct {
+ #define NGHTTP2_CLIENT_MAGIC_LEN 24
+
+ /**
++ * @macro
++ *
++ * The default max number of settings per SETTINGS frame
++ */
++#define NGHTTP2_DEFAULT_MAX_SETTINGS 32
++
++/**
+ * @enum
+ *
+ * Error codes used in this library. The code range is [-999, -500],
+@@ -399,6 +406,11 @@ typedef enum {
+ */
+ NGHTTP2_ERR_SETTINGS_EXPECTED = -536,
+ /**
++ * When a local endpoint receives too many settings entries
++ * in a single SETTINGS frame.
++ */
++ NGHTTP2_ERR_TOO_MANY_SETTINGS = -537,
++ /**
+ * The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
+ * under unexpected condition and processing was terminated (e.g.,
+ * out of memory). If application receives this error code, it must
+@@ -2661,6 +2673,17 @@ NGHTTP2_EXTERN void nghttp2_option_set_m
+
+ /**
+ * @function
++ *
++ * This function sets the maximum number of SETTINGS entries per
++ * SETTINGS frame that will be accepted. If more than those entries
++ * are received, the peer is considered to be misbehaving and session
++ * will be closed. The default value is 32.
++ */
++NGHTTP2_EXTERN void nghttp2_option_set_max_settings(nghttp2_option *option,
++ size_t val);
++
++/**
++ * @function
+ *
+ * Initializes |*session_ptr| for client use. The all members of
+ * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
+Index: nghttp2-1.40.0/lib/nghttp2_helper.c
+===================================================================
+--- nghttp2-1.40.0.orig/lib/nghttp2_helper.c
++++ nghttp2-1.40.0/lib/nghttp2_helper.c
+@@ -334,6 +334,8 @@ const char *nghttp2_strerror(int error_c
+ case NGHTTP2_ERR_FLOODED:
+ return "Flooding was detected in this HTTP/2 session, and it must be "
+ "closed";
++ case NGHTTP2_ERR_TOO_MANY_SETTINGS:
++ return "SETTINGS frame contained more than the maximum allowed entries";
+ default:
+ return "Unknown error code";
+ }
+Index: nghttp2-1.40.0/lib/nghttp2_option.c
+===================================================================
+--- nghttp2-1.40.0.orig/lib/nghttp2_option.c
++++ nghttp2-1.40.0/lib/nghttp2_option.c
+@@ -121,3 +121,8 @@ void nghttp2_option_set_max_outbound_ack
+ option->opt_set_mask |= NGHTTP2_OPT_MAX_OUTBOUND_ACK;
+ option->max_outbound_ack = val;
+ }
++
++void nghttp2_option_set_max_settings(nghttp2_option *option, size_t val) {
++ option->opt_set_mask |= NGHTTP2_OPT_MAX_SETTINGS;
++ option->max_settings = val;
++}
+Index: nghttp2-1.40.0/lib/nghttp2_option.h
+===================================================================
+--- nghttp2-1.40.0.orig/lib/nghttp2_option.h
++++ nghttp2-1.40.0/lib/nghttp2_option.h
+@@ -67,6 +67,7 @@ typedef enum {
+ NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9,
+ NGHTTP2_OPT_NO_CLOSED_STREAMS = 1 << 10,
+ NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11,
++ NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
+ } nghttp2_option_flag;
+
+ /**
+@@ -86,6 +87,10 @@ struct nghttp2_option {
+ */
+ size_t max_outbound_ack;
+ /**
++ * NGHTTP2_OPT_MAX_SETTINGS
++ */
++ size_t max_settings;
++ /**
+ * Bitwise OR of nghttp2_option_flag to determine that which fields
+ * are specified.
+ */
+Index: nghttp2-1.40.0/lib/nghttp2_session.c
+===================================================================
+--- nghttp2-1.40.0.orig/lib/nghttp2_session.c
++++ nghttp2-1.40.0/lib/nghttp2_session.c
+@@ -458,6 +458,7 @@ static int session_new(nghttp2_session *
+
+ (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN;
+ (*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM;
++ (*session_ptr)->max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS;
+
+ if (option) {
+ if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) &&
+@@ -521,6 +522,11 @@ static int session_new(nghttp2_session *
+ if (option->opt_set_mask & NGHTTP2_OPT_MAX_OUTBOUND_ACK) {
+ (*session_ptr)->max_outbound_ack = option->max_outbound_ack;
+ }
++
++ if ((option->opt_set_mask & NGHTTP2_OPT_MAX_SETTINGS) &&
++ option->max_settings) {
++ (*session_ptr)->max_settings = option->max_settings;
++ }
+ }
+
+ rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
+@@ -5694,6 +5700,16 @@ ssize_t nghttp2_session_mem_recv(nghttp2
+ iframe->max_niv =
+ iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
+
++ if (iframe->max_niv - 1 > session->max_settings) {
++ rv = nghttp2_session_terminate_session_with_reason(
++ session, NGHTTP2_ENHANCE_YOUR_CALM,
++ "SETTINGS: too many setting entries");
++ if (nghttp2_is_fatal(rv)) {
++ return rv;
++ }
++ return (ssize_t)inlen;
++ }
++
+ iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
+ iframe->max_niv);
+
+@@ -7460,6 +7476,11 @@ static int nghttp2_session_upgrade_inter
+ if (settings_payloadlen % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
++ /* SETTINGS frame contains too many settings */
++ if (settings_payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH
++ > session->max_settings) {
++ return NGHTTP2_ERR_TOO_MANY_SETTINGS;
++ }
+ rv = nghttp2_frame_unpack_settings_payload2(&iv, &niv, settings_payload,
+ settings_payloadlen, mem);
+ if (rv != 0) {
+Index: nghttp2-1.40.0/lib/nghttp2_session.h
+===================================================================
+--- nghttp2-1.40.0.orig/lib/nghttp2_session.h
++++ nghttp2-1.40.0/lib/nghttp2_session.h
+@@ -267,6 +267,8 @@ struct nghttp2_session {
+ /* The maximum length of header block to send. Calculated by the
+ same way as nghttp2_hd_deflate_bound() does. */
+ size_t max_send_header_block_length;
++ /* The maximum number of settings accepted per SETTINGS frame. */
++ size_t max_settings;
+ /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
+ uint32_t next_stream_id;
+ /* The last stream ID this session initiated. For client session,
+Index: nghttp2-1.40.0/tests/main.c
+===================================================================
+--- nghttp2-1.40.0.orig/tests/main.c
++++ nghttp2-1.40.0/tests/main.c
+@@ -315,6 +315,8 @@ int main() {
+ test_nghttp2_session_set_local_window_size) ||
+ !CU_add_test(pSuite, "session_cancel_from_before_frame_send",
+ test_nghttp2_session_cancel_from_before_frame_send) ||
++ !CU_add_test(pSuite, "session_too_many_settings",
++ test_nghttp2_session_too_many_settings) ||
+ !CU_add_test(pSuite, "session_removed_closed_stream",
+ test_nghttp2_session_removed_closed_stream) ||
+ !CU_add_test(pSuite, "session_pause_data",
+Index: nghttp2-1.40.0/tests/nghttp2_session_test.c
+===================================================================
+--- nghttp2-1.40.0.orig/tests/nghttp2_session_test.c
++++ nghttp2-1.40.0/tests/nghttp2_session_test.c
+@@ -10558,6 +10558,67 @@ void test_nghttp2_session_cancel_from_be
+ nghttp2_session_del(session);
+ }
+
++void test_nghttp2_session_too_many_settings(void) {
++ nghttp2_session *session;
++ nghttp2_option *option;
++ nghttp2_session_callbacks callbacks;
++ nghttp2_frame frame;
++ nghttp2_bufs bufs;
++ nghttp2_buf *buf;
++ ssize_t rv;
++ my_user_data ud;
++ nghttp2_settings_entry iv[3];
++ nghttp2_mem *mem;
++ nghttp2_outbound_item *item;
++
++ mem = nghttp2_mem_default();
++ frame_pack_bufs_init(&bufs);
++
++ memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
++ callbacks.on_frame_recv_callback = on_frame_recv_callback;
++ callbacks.send_callback = null_send_callback;
++
++ nghttp2_option_new(&option);
++ nghttp2_option_set_max_settings(option, 1);
++
++ nghttp2_session_client_new2(&session, &callbacks, &ud, option);
++
++ CU_ASSERT(1 == session->max_settings);
++
++ nghttp2_option_del(option);
++
++ iv[0].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
++ iv[0].value = 3000;
++
++ iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
++ iv[1].value = 16384;
++
++ nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, dup_iv(iv, 2),
++ 2);
++
++ rv = nghttp2_frame_pack_settings(&bufs, &frame.settings);
++
++ CU_ASSERT(0 == rv);
++ CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
++
++ nghttp2_frame_settings_free(&frame.settings, mem);
++
++ buf = &bufs.head->buf;
++ assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
++
++ ud.frame_recv_cb_called = 0;
++
++ rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
++ CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
++
++ item = nghttp2_session_get_next_ob_item(session);
++ CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
++
++ nghttp2_bufs_reset(&bufs);
++ nghttp2_bufs_free(&bufs);
++ nghttp2_session_del(session);
++}
++
+ static void
+ prepare_session_removed_closed_stream(nghttp2_session *session,
+ nghttp2_hd_deflater *deflater) {
+Index: nghttp2-1.40.0/tests/nghttp2_session_test.h
+===================================================================
+--- nghttp2-1.40.0.orig/tests/nghttp2_session_test.h
++++ nghttp2-1.40.0/tests/nghttp2_session_test.h
+@@ -156,6 +156,7 @@ void test_nghttp2_session_repeated_prior
+ void test_nghttp2_session_repeated_priority_submission(void);
+ void test_nghttp2_session_set_local_window_size(void);
+ void test_nghttp2_session_cancel_from_before_frame_send(void);
++void test_nghttp2_session_too_many_settings(void);
+ void test_nghttp2_session_removed_closed_stream(void);
+ void test_nghttp2_session_pause_data(void);
+ void test_nghttp2_session_no_closed_streams(void);
+Index: nghttp2-1.40.0/doc/Makefile.am
+===================================================================
+--- nghttp2-1.40.0.orig/doc/Makefile.am
++++ nghttp2-1.40.0/doc/Makefile.am
+@@ -69,6 +69,7 @@ APIDOCS= \
+ nghttp2_option_set_peer_max_concurrent_streams.rst \
+ nghttp2_option_set_user_recv_extension_type.rst \
+ nghttp2_option_set_max_outbound_ack.rst \
++ nghttp2_option_set_max_settings.rst \
+ nghttp2_pack_settings_payload.rst \
+ nghttp2_priority_spec_check_default.rst \
+ nghttp2_priority_spec_default_init.rst \