unbound: patch CVE-2026-55991

Details:
https://nvd.nist.gov/vuln/detail/cve-2026-55991

Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
Ankur Tyagi
2026-09-15 10:14:04 +05:30
committed by Anuj Mittal
parent b18b97d782
commit 5401a83771
2 changed files with 113 additions and 0 deletions
@@ -0,0 +1,112 @@
From 355213b9175382db5e86e49731aa939a533b1b03 Mon Sep 17 00:00:00 2001
From: "W.C.A. Wijngaards" <wouter@nlnetlabs.nl>
Date: Wed, 22 Jul 2026 10:19:02 +0200
Subject: [PATCH] - Fix CVE-2026-55991, Remote DNS-over-QUIC (DoQ) flow-control
assertion failure in libngtcp2. Thanks to Qifan Zhang, Palo Alto
Networks, for the report. In addition, thanks to Xuanchao Xie, for also
reporting this issue.
(cherry picked from commit aac261cbb3795cbd60af2f37ef57bfa5c186aae6)
CVE: CVE-2026-55991
Upstream-Status: Backport [https://github.com/NLnetLabs/unbound/commit/aac261cbb3795cbd60af2f37ef57bfa5c186aae6]
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
---
services/listen_dnsport.c | 46 +++++++++++++++++++++++++++------------
testcode/doqclient.c | 4 ++--
2 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c
index 3c5010b6b..d49d4ad4c 100644
--- a/services/listen_dnsport.c
+++ b/services/listen_dnsport.c
@@ -4472,6 +4472,29 @@ doq_stream_reset_cb(ngtcp2_conn* ATTR_UNUSED(conn), int64_t stream_id,
return 0;
}
+/** ngtcp2 extend_max_stream_data function */
+int doq_extend_max_stream_data_cb(ngtcp2_conn* ATTR_UNUSED(conn),
+ int64_t stream_id, uint64_t max_data, void* user_data,
+ void* ATTR_UNUSED(stream_user_data))
+{
+ struct doq_conn* doq_conn = (struct doq_conn*)user_data;
+ struct doq_stream* stream;
+ verbose(VERB_ALGO, "doq extend_max_stream_data stream id %d "
+ "max_data %d ", (int)stream_id, (int)max_data);
+ if(max_data == 0)
+ return 0;
+ stream = doq_stream_find(doq_conn, stream_id);
+ if(!stream) {
+ verbose(VERB_ALGO, "doq: unknown stream %d", (int)stream_id);
+ return 0;
+ }
+ if(!stream->is_answer_available)
+ return 0;
+ doq_stream_on_write_list(doq_conn, stream);
+ doq_conn_write_enable(doq_conn);
+ return 0;
+}
+
/** ngtcp2 acked_stream_data_offset callback function */
static int
doq_acked_stream_data_offset_cb(ngtcp2_conn* ATTR_UNUSED(conn),
@@ -4846,6 +4869,7 @@ doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
callbacks.stream_open = doq_stream_open_cb;
callbacks.stream_close = doq_stream_close_cb;
callbacks.stream_reset = doq_stream_reset_cb;
+ callbacks.extend_max_stream_data = doq_extend_max_stream_data_cb;
callbacks.acked_stream_data_offset = doq_acked_stream_data_offset_cb;
callbacks.recv_stream_data = doq_recv_stream_data_cb;
@@ -5427,26 +5451,20 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
continue;
} else if(ret == NGTCP2_ERR_STREAM_DATA_BLOCKED) {
verbose(VERB_ALGO, "doq: ngtcp2_conn_writev_stream returned NGTCP2_ERR_STREAM_DATA_BLOCKED");
-#ifdef HAVE_NGTCP2_CCERR_DEFAULT
- ngtcp2_ccerr_set_application_error(
- &conn->ccerr, -1, NULL, 0);
-#else
- ngtcp2_connection_close_error_set_application_error(&conn->last_error, -1, NULL, 0);
-#endif
- if(err_drop)
- *err_drop = 0;
- if(!doq_conn_close_error(c, conn)) {
- if(err_drop)
- *err_drop = 1;
+ if(stream) {
+ doq_stream_off_write_list(conn, stream);
+ stream = stream->write_next;
+ continue;
+ } else {
+ break;
}
- return 0;
} else if(ret == NGTCP2_ERR_STREAM_SHUT_WR) {
verbose(VERB_ALGO, "doq: ngtcp2_conn_writev_stream returned NGTCP2_ERR_STREAM_SHUT_WR");
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
ngtcp2_ccerr_set_application_error(
- &conn->ccerr, -1, NULL, 0);
+ &conn->ccerr, DOQ_APP_ERROR_CODE, NULL, 0);
#else
- ngtcp2_connection_close_error_set_application_error(&conn->last_error, -1, NULL, 0);
+ ngtcp2_connection_close_error_set_application_error(&conn->last_error, DOQ_APP_ERROR_CODE, NULL, 0);
#endif
if(err_drop)
*err_drop = 0;
diff --git a/testcode/doqclient.c b/testcode/doqclient.c
index 1994cd097..3cb25c98b 100644
--- a/testcode/doqclient.c
+++ b/testcode/doqclient.c
@@ -1519,9 +1519,9 @@ doq_client_send_pkt(struct doq_client_data* data, uint32_t ecn, uint8_t* buf,
}
log_err("doq sendmsg: %s", strerror(errno));
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
- ngtcp2_ccerr_set_application_error(&data->ccerr, -1, NULL, 0);
+ ngtcp2_ccerr_set_application_error(&data->ccerr, 1, NULL, 0);
#else
- ngtcp2_connection_close_error_set_application_error(&data->last_error, -1, NULL, 0);
+ ngtcp2_connection_close_error_set_application_error(&data->last_error, 1, NULL, 0);
#endif
return 0;
}
@@ -40,6 +40,7 @@ SRC_URI = "git://github.com/NLnetLabs/unbound.git;protocol=https;branch=master;t
file://CVE-2026-55717.patch \
file://CVE-2026-55973.patch \
file://CVE-2026-55990.patch \
file://CVE-2026-55991.patch \
"
SRCREV = "f6269baa605d31859f28770e01a24e3677e5f82c"