summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/recipes-support/nghttp2/nghttp2/CVE-2023-35945.patch151
-rw-r--r--meta/recipes-support/nghttp2/nghttp2_1.52.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..04d2086e1c
--- /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: Mon, 4 Sep 2023 06:48:30 +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 93f3f07..9bb32b2 100644
57--- a/lib/nghttp2_session.c
58+++ b/lib/nghttp2_session.c
59@@ -3300,6 +3300,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@@ -3342,19 +3343,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 08152d4..14ab132 100644
93--- a/tests/nghttp2_session_test.c
94+++ b/tests/nghttp2_session_test.c
95@@ -585,6 +585,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@@ -4297,6 +4306,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@@ -4338,6 +4349,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.52.0.bb b/meta/recipes-support/nghttp2/nghttp2_1.52.0.bb
index f57a15954d..0fba554919 100644
--- a/meta/recipes-support/nghttp2/nghttp2_1.52.0.bb
+++ b/meta/recipes-support/nghttp2/nghttp2_1.52.0.bb
@@ -7,6 +7,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=764abdf30b2eadd37ce47dcbce0ea1ec"
7SRC_URI = "\ 7SRC_URI = "\
8 ${GITHUB_BASE_URI}/download/v${PV}/nghttp2-${PV}.tar.xz \ 8 ${GITHUB_BASE_URI}/download/v${PV}/nghttp2-${PV}.tar.xz \
9 file://0001-fetch-ocsp-response-use-python3.patch \ 9 file://0001-fetch-ocsp-response-use-python3.patch \
10 file://CVE-2023-35945.patch \
10" 11"
11SRC_URI[sha256sum] = "3ea9f0439e60469ad4d39cb349938684ffb929dd7e8e06a7bffe9f9d21f8ba7d" 12SRC_URI[sha256sum] = "3ea9f0439e60469ad4d39cb349938684ffb929dd7e8e06a7bffe9f9d21f8ba7d"
12 13