Fix CVE-2026-41292: DoS via excessive EDNS options

More information can be found in the upstream's advisory:
https://nlnetlabs.nl/downloads/unbound/CVE-2026-41292.txt

Resolves-Vulnerability: CVE-2026-41292
Resolves: RHEL-187346
This commit is contained in:
Fedor Vorobev 2026-06-24 11:39:42 +02:00
parent 998627c879
commit c2fe64e3f1
2 changed files with 68 additions and 1 deletions

View File

@ -0,0 +1,64 @@
diff --git a/unbound-1.16.2/util/data/msgparse.c b/unbound-1.16.2/util/data/msgparse.c
index 7a51441..0ffdb3d 100644
--- a/unbound-1.16.2/util/data/msgparse.c
+++ b/unbound-1.16.2/util/data/msgparse.c
@@ -50,6 +50,8 @@
#include "sldns/parseutil.h"
#include "sldns/wire2str.h"
+#define MAX_PARSED_EDNS_OPTIONS 100
+
/** smart comparison of (compressed, valid) dnames from packet */
static int
smart_compare(sldns_buffer* pkt, uint8_t* dnow,
@@ -957,7 +959,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
struct edns_data* edns, struct config_file* cfg, struct comm_point* c,
struct regional* region)
{
- int nsid_seen = 0, padding_seen = 0;
+ int i = 0, nsid_seen = 0, padding_seen = 0;
/* To respond with a Keepalive option, the client connection must have
* received one message with a TCP Keepalive EDNS option, and that
* option must have 0 length data. Subsequent messages sent on that
@@ -977,7 +979,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
/* while still more options, and have code+len to read */
/* ignores partial content (i.e. rdata len 3) */
- while(rdata_len >= 4) {
+ while(rdata_len >= 4 && i < MAX_PARSED_EDNS_OPTIONS) {
uint16_t opt_code = sldns_read_uint16(rdata_ptr);
uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
rdata_ptr += 4;
@@ -1054,6 +1056,7 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
}
rdata_ptr += opt_len;
rdata_len -= opt_len;
+ i++;
}
return LDNS_RCODE_NOERROR;
}
@@ -1068,6 +1071,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg,
struct rrset_parse* found_prev = 0;
size_t rdata_len;
uint8_t* rdata_ptr;
+ int i = 0;
/* since the class encodes the UDP size, we cannot use hash table to
* find the EDNS OPT record. Scan the packet. */
while(rrset) {
@@ -1125,7 +1129,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg,
/* while still more options, and have code+len to read */
/* ignores partial content (i.e. rdata len 3) */
- while(rdata_len >= 4) {
+ while(rdata_len >= 4 && i < MAX_PARSED_EDNS_OPTIONS) {
uint16_t opt_code = sldns_read_uint16(rdata_ptr);
uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
rdata_ptr += 4;
@@ -1140,6 +1144,7 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg,
}
rdata_ptr += opt_len;
rdata_len -= opt_len;
+ i++;
}
/* ignore rrsigs */
return LDNS_RCODE_NOERROR;

View File

@ -88,7 +88,8 @@ Patch10: unbound-1.25.1-CVE-2026-40622.patch
Patch11: unbound-1.25.1-CVE-2026-40622-test.patch
# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-44390.diff
Patch12: unbound-1.25.1-CVE-2026-44390.patch
# https://nlnetlabs.nl/downloads/unbound/patch_CVE-2026-41292.diff
Patch13: unbound-1.25.1-CVE-2026-41292.patch
BuildRequires: gdb
BuildRequires: gcc, make
@ -200,6 +201,7 @@ pushd %{pkgname}
%patch10 -p2 -b .CVE-2026-40622
%patch11 -p2 -b .CVE-2026-40622-test
%patch12 -p2 -b .CVE-2026-44390
%patch13 -p2 -b .CVE-2026-41292
# copy common doc files - after here, since it may be patched
cp -pr doc pythonmod libunbound ../
@ -469,6 +471,7 @@ popd
* Tue Jun 23 2026 Fedor Vorobev <fvorobev@redhat.com> - 1.16.2-5.12
- Fix CVE-2026-40622 (RHEL-184832)
- Fix CVE-2026-44390 (RHEL-186680)
- Fix CVE-2026-41292 (RHEL-187346)
* Mon May 25 2026 Fedor Vorobev <fvorobev@redhat.com> - 1.16.2-5.11
- Fix CVE-2026-42944 (RHEL177909)