From a8e3b20df3e1a97601bc54da9b2f1405c2056f7b Mon Sep 17 00:00:00 2001 From: Rahul Taya Date: Thu, 25 Feb 2021 13:02:59 +0530 Subject: nghttp2: Add fix for CVE-2020-11080 Added below two patches to fix CVE-2020-11080: 1. CVE-2020-11080-1.patch 2. CVE-2020-11080-2.patch Signed-off-by: Rahul Taya [Refreshed patches to apply] Signed-off-by: Armin Kuster --- .../nghttp2/nghttp2/CVE-2020-11080-1.patch | 31 +++ .../nghttp2/nghttp2/CVE-2020-11080-2.patch | 308 +++++++++++++++++++++ .../recipes-support/nghttp2/nghttp2_1.40.0.bb | 2 + 3 files changed, 341 insertions(+) create mode 100644 meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-1.patch create mode 100644 meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-2.patch (limited to 'meta-networking/recipes-support/nghttp2') diff --git a/meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-1.patch b/meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-1.patch new file mode 100644 index 0000000000..ca181bb4b2 --- /dev/null +++ b/meta-networking/recipes-support/nghttp2/nghttp2/CVE-2020-11080-1.patch @@ -0,0 +1,31 @@ +From f8da73bd042f810f34d19f9eae02b46d870af394 Mon Sep 17 00:00:00 2001 +From: James M Snell +Date: Sun, 19 Apr 2020 09:12:24 -0700 +Subject: [PATCH] Earlier check for settings flood + +CVE: CVE-2020-11080 +Upstream-Status: Backport [https://github.com/nghttp2/nghttp2/commit/f8da73bd042f810f34d19f9eae02b46d870af394.patch] +Comment: No hunk refreshed +Affects-version: < v1.41.0 +Signed-off-by: Rahul Taya +--- + lib/nghttp2_session.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +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 +@@ -5678,6 +5678,12 @@ ssize_t nghttp2_session_mem_recv(nghttp2 + break; + } + ++ /* Check the settings flood counter early to be safe */ ++ if (session->obq_flood_counter_ >= session->max_outbound_ack && ++ !(iframe->frame.hd.flags & NGHTTP2_FLAG_ACK)) { ++ return NGHTTP2_ERR_FLOODED; ++ } ++ + iframe->state = NGHTTP2_IB_READ_SETTINGS; + + if (iframe->payloadleft) { 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 +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 +--- + 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 \ diff --git a/meta-networking/recipes-support/nghttp2/nghttp2_1.40.0.bb b/meta-networking/recipes-support/nghttp2/nghttp2_1.40.0.bb index 9ed8c56420..b497058ca6 100644 --- a/meta-networking/recipes-support/nghttp2/nghttp2_1.40.0.bb +++ b/meta-networking/recipes-support/nghttp2/nghttp2_1.40.0.bb @@ -10,6 +10,8 @@ UPSTREAM_CHECK_URI = "https://github.com/nghttp2/nghttp2/releases" SRC_URI = "\ https://github.com/nghttp2/nghttp2/releases/download/v${PV}/nghttp2-${PV}.tar.xz \ file://0001-fetch-ocsp-response-use-python3.patch \ + file://CVE-2020-11080-1.patch \ + file://CVE-2020-11080-2.patch \ " SRC_URI[md5sum] = "8d1a6b96760254e4dd142d7176e8fb7c" SRC_URI[sha256sum] = "09fc43d428ff237138733c737b29fb1a7e49d49de06d2edbed3bc4cdcee69073" -- cgit 1.2.3-korg