summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYogita Urade <yogita.urade@windriver.com>2023-08-25 08:45:26 +0000
committerSteve Sakoman <steve@sakoman.com>2023-08-30 04:46:36 -1000
commit1cae56f2168095927b6deafef9328a07f061c096 (patch)
tree41309bb999a549c3eb728dc2f857af502a0e58ac
parent074ad15e1e34007997e58892daf759c8d6d9abff (diff)
downloadpoky-1cae56f2168095927b6deafef9328a07f061c096.tar.gz
nghttp2: fix CVE-2023-35945
Envoy is a cloud-native high-performance edge/middle/service proxy. Envoy’s HTTP/2 codec may leak a header map and bookkeeping structures upon receiving `RST_STREAM` immediately followed by the `GOAWAY` frames from an upstream server. In nghttp2, cleanup of pending requests due to receipt of the `GOAWAY` frame skips de-allocation of the bookkeeping structure and pending compressed header. The error return [code path] is taken if connection is already marked for not sending more requests due to `GOAWAY` frame. The clean-up code is right after the return statement, causing memory leak. Denial of service through memory exhaustion. This vulnerability was patched in versions(s) 1.26.3, 1.25.8, 1.24.9, 1.23.11. References: https://nvd.nist.gov/vuln/detail/CVE-2023-35945 https://github.com/envoyproxy/envoy/security/advisories/GHSA-jfxv-29pc-x22r (From OE-Core rev: 0e6eb0f417079eaf76b003973c9d93338e6363b5) Signed-off-by: Yogita Urade <yogita.urade@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-support/nghttp2/nghttp2/CVE-2023-35945.patch151
-rw-r--r--meta/recipes-support/nghttp2/nghttp2_1.47.0.bb1
2 files changed, 152 insertions, 0 deletions
diff --git a/meta/recipes-support/nghttp2/nghttp2/CVE-2023-35945.patch b/meta/recipes-support/nghttp2/nghttp2/CVE-2023-35945.patch
new file mode 100644
index 0000000000..e03915fda8
--- /dev/null
+++ b/meta/recipes-support/nghttp2/nghttp2/CVE-2023-35945.patch
@@ -0,0 +1,151 @@
1From ce385d3f55a4b76da976b3bdf71fe2deddf315ba Mon Sep 17 00:00:00 2001
2From: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
3Date: Thu, 24 Aug 2023 09:34:26 +0000
4Subject: [PATCH] Fix memory leak
5
6This commit fixes memory leak that happens when PUSH_PROMISE or
7HEADERS frame cannot be sent, and nghttp2_on_stream_close_callback
8fails with a fatal error. For example, if GOAWAY frame has been
9received, a HEADERS frame that opens new stream cannot be sent.
10
11This issue has already been made public via CVE-2023-35945 [1] issued
12by envoyproxy/envoy project. During embargo period, the patch to fix
13this bug was accidentally submitted to nghttp2/nghttp2 repository [2].
14And they decided to disclose CVE early. I was notified just 1.5 hours
15before disclosure. I had no time to respond.
16
17PoC described in [1] is quite simple, but I think it is not enough to
18trigger this bug. While it is true that receiving GOAWAY prevents a
19client from opening new stream, and nghttp2 enters error handling
20branch, in order to cause the memory leak,
21nghttp2_session_close_stream function must return a fatal error.
22nghttp2 defines 2 fatal error codes:
23
24- NGHTTP2_ERR_NOMEM
25- NGHTTP2_ERR_CALLBACK_FAILURE
26
27NGHTTP2_ERR_NOMEM, as its name suggests, indicates out of memory. It
28is unlikely that a process gets short of memory with this simple PoC
29scenario unless application does something memory heavy processing.
30
31NGHTTP2_ERR_CALLBACK_FAILURE is returned from application defined
32callback function (nghttp2_on_stream_close_callback, in this case),
33which indicates something fatal happened inside a callback, and a
34connection must be closed immediately without any further action. As
35nghttp2_on_stream_close_error_callback documentation says, any error
36code other than 0 or NGHTTP2_ERR_CALLBACK_FAILURE is treated as fatal
37error code. More specifically, it is treated as if
38NGHTTP2_ERR_CALLBACK_FAILURE is returned. I guess that envoy returns
39NGHTTP2_ERR_CALLBACK_FAILURE or other error code which is translated
40into NGHTTP2_ERR_CALLBACK_FAILURE.
41
42[1] https://github.com/envoyproxy/envoy/security/advisories/GHSA-jfxv-29pc-x22r
43[2] https://github.com/nghttp2/nghttp2/pull/1929
44
45CVE: CVE-2023-35945
46
47Upstream-Status: Backport [https://github.com/nghttp2/nghttp2/commit/ce385d3f55a4b76da976b3bdf71fe2deddf315ba]
48
49Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
50---
51 lib/nghttp2_session.c | 10 +++++-----
52 tests/nghttp2_session_test.c | 34 ++++++++++++++++++++++++++++++++++
53 2 files changed, 39 insertions(+), 5 deletions(-)
54
55diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c
56index 380a47c..2d9285f 100644
57--- a/lib/nghttp2_session.c
58+++ b/lib/nghttp2_session.c
59@@ -2940,6 +2940,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
60 if (rv < 0) {
61 int32_t opened_stream_id = 0;
62 uint32_t error_code = NGHTTP2_INTERNAL_ERROR;
63+ int rv2 = 0;
64
65 DEBUGF("send: frame preparation failed with %s\n",
66 nghttp2_strerror(rv));
67@@ -2982,19 +2983,18 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
68 }
69 if (opened_stream_id) {
70 /* careful not to override rv */
71- int rv2;
72 rv2 = nghttp2_session_close_stream(session, opened_stream_id,
73 error_code);
74-
75- if (nghttp2_is_fatal(rv2)) {
76- return rv2;
77- }
78 }
79
80 nghttp2_outbound_item_free(item, mem);
81 nghttp2_mem_free(mem, item);
82 active_outbound_item_reset(aob, mem);
83
84+ if (nghttp2_is_fatal(rv2)) {
85+ return rv2;
86+ }
87+
88 if (rv == NGHTTP2_ERR_HEADER_COMP) {
89 /* If header compression error occurred, should terminiate
90 connection. */
91diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c
92index cb6bdf7..c2778bc 100644
93--- a/tests/nghttp2_session_test.c
94+++ b/tests/nghttp2_session_test.c
95@@ -584,6 +584,15 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
96 return 0;
97 }
98
99+static int fatal_error_on_stream_close_callback(nghttp2_session *session,
100+ int32_t stream_id,
101+ uint32_t error_code,
102+ void *user_data) {
103+ on_stream_close_callback(session, stream_id, error_code, user_data);
104+
105+ return NGHTTP2_ERR_CALLBACK_FAILURE;
106+}
107+
108 static ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf,
109 size_t len, const nghttp2_frame *frame,
110 void *user_data) {
111@@ -3906,6 +3915,8 @@ void test_nghttp2_session_on_goaway_received(void) {
112 nghttp2_frame frame;
113 int i;
114 nghttp2_mem *mem;
115+ const uint8_t *data;
116+ ssize_t datalen;
117
118 mem = nghttp2_mem_default();
119 user_data.frame_recv_cb_called = 0;
120@@ -3947,6 +3958,29 @@ void test_nghttp2_session_on_goaway_received(void) {
121
122 nghttp2_frame_goaway_free(&frame.goaway, mem);
123 nghttp2_session_del(session);
124+
125+ /* Make sure that no memory leak when stream_close callback fails
126+ with a fatal error */
127+ memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
128+ callbacks.on_stream_close_callback = fatal_error_on_stream_close_callback;
129+
130+ memset(&user_data, 0, sizeof(user_data));
131+
132+ nghttp2_session_client_new(&session, &callbacks, &user_data);
133+
134+ nghttp2_frame_goaway_init(&frame.goaway, 0, NGHTTP2_NO_ERROR, NULL, 0);
135+
136+ CU_ASSERT(0 == nghttp2_session_on_goaway_received(session, &frame));
137+
138+ nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL);
139+
140+ datalen = nghttp2_session_mem_send(session, &data);
141+
142+ CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == datalen);
143+ CU_ASSERT(1 == user_data.stream_close_cb_called);
144+
145+ nghttp2_frame_goaway_free(&frame.goaway, mem);
146+ nghttp2_session_del(session);
147 }
148
149 void test_nghttp2_session_on_window_update_received(void) {
150--
1512.35.5
diff --git a/meta/recipes-support/nghttp2/nghttp2_1.47.0.bb b/meta/recipes-support/nghttp2/nghttp2_1.47.0.bb
index 90d3286ac6..0b9091f7e8 100644
--- a/meta/recipes-support/nghttp2/nghttp2_1.47.0.bb
+++ b/meta/recipes-support/nghttp2/nghttp2_1.47.0.bb
@@ -9,6 +9,7 @@ UPSTREAM_CHECK_URI = "https://github.com/nghttp2/nghttp2/releases"
9SRC_URI = "\ 9SRC_URI = "\
10 https://github.com/nghttp2/nghttp2/releases/download/v${PV}/nghttp2-${PV}.tar.xz \ 10 https://github.com/nghttp2/nghttp2/releases/download/v${PV}/nghttp2-${PV}.tar.xz \
11 file://0001-fetch-ocsp-response-use-python3.patch \ 11 file://0001-fetch-ocsp-response-use-python3.patch \
12 file://CVE-2023-35945.patch \
12" 13"
13SRC_URI[sha256sum] = "68271951324554c34501b85190f22f2221056db69f493afc3bbac8e7be21e7cc" 14SRC_URI[sha256sum] = "68271951324554c34501b85190f22f2221056db69f493afc3bbac8e7be21e7cc"
14 15