unbound: patch CVE-2026-42923

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

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:13:54 +05:30
committed by Anuj Mittal
parent 11bc965378
commit 5d793b6ca9
2 changed files with 115 additions and 0 deletions
@@ -0,0 +1,114 @@
From 7a2457c979cdc1f0c1bb1fe68010fdd2f46398f2 Mon Sep 17 00:00:00 2001
From: "W.C.A. Wijngaards" <wouter@nlnetlabs.nl>
Date: Wed, 20 May 2026 10:20:02 +0200
Subject: [PATCH] - Fix CVE-2026-42923, Degradation of service with unbounded
NSEC3 hash calculations. Thanks to Qifan Zhang, Palo Alto Networks, for
the report.
(cherry picked from commit c343fff3a4de922835fec7232b90faed658b5371)
CVE: CVE-2026-42923
Upstream-Status: Backport [https://github.com/NLnetLabs/unbound/commit/c343fff3a4de922835fec7232b90faed658b5371]
Dropped changes to the Changelog file.
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
---
validator/val_neg.c | 28 +++++++++++++++++++++++++++-
validator/val_nsec3.c | 5 -----
validator/val_nsec3.h | 6 ++++++
3 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/validator/val_neg.c b/validator/val_neg.c
index bc3a83aeb..0f2751121 100644
--- a/validator/val_neg.c
+++ b/validator/val_neg.c
@@ -62,6 +62,13 @@
#include "sldns/rrdef.h"
#include "sldns/sbuffer.h"
+/**
+ * The maximum salt length that the negative cache is willing to use.
+ * Larger salt increases the computation time, while recommendations are
+ * for zero salt length for zones.
+ */
+#define MAX_SALT_LENGTH 64
+
int val_neg_data_compare(const void* a, const void* b)
{
struct val_neg_data* x = (struct val_neg_data*)a;
@@ -826,7 +833,11 @@ void neg_insert_data(struct val_neg_cache* neg,
(slen != 0 && zone->nsec3_salt && s
&& memcmp(zone->nsec3_salt, s, slen) != 0))) {
- if(slen > 0) {
+ if(slen > MAX_SALT_LENGTH) {
+ /* RFC 9276 s3.1: operators SHOULD NOT use a salt; large
+ * salts inflate per-hash block count. Decline to cache. */
+ return;
+ } else if(slen > 0) {
uint8_t* sa = memdup(s, slen);
if(sa) {
free(zone->nsec3_salt);
@@ -1169,6 +1180,15 @@ neg_find_nsec3_ce(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
uint8_t hashce[NSEC3_SHA_LEN];
uint8_t b32[257];
size_t celen, b32len;
+ int hashmax = MAX_NSEC3_CALCULATIONS;
+ if(qlabs > hashmax) {
+ /* strip leading labels so the walk costs at most
+ * MAX_NSEC3_CALCULATIONS hashes, mirroring val_nsec3.c */
+ while(qlabs > hashmax) {
+ dname_remove_label(&qname, &qname_len);
+ qlabs--;
+ }
+ }
*nclen = 0;
while(qlabs > 0) {
@@ -1269,6 +1289,12 @@ neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
if(!zone->nsec3_hash)
return NULL; /* not nsec3 zone */
+ if(!topname && qlabs > zone->labs + 1)
+ return NULL; /* iterator caller; opt-out proof would be discarded
+ * at the !topname check below anyway.
+ * The qlabs check allows the exact-match for
+ * the one-label-below-zone case. */
+
if(!(data=neg_find_nsec3_ce(zone, qname, qname_len, qlabs, buf,
hashnc, &nclen))) {
return NULL;
diff --git a/validator/val_nsec3.c b/validator/val_nsec3.c
index 92d853825..62effde20 100644
--- a/validator/val_nsec3.c
+++ b/validator/val_nsec3.c
@@ -59,11 +59,6 @@
#include "sldns/sbuffer.h"
#include "util/config_file.h"
-/**
- * Max number of NSEC3 calculations at once, suspend query for later.
- * 8 is low enough and allows for cases where multiple proofs are needed.
- */
-#define MAX_NSEC3_CALCULATIONS 8
/**
* When all allowed NSEC3 calculations at once resulted in error treat as
* bogus. NSEC3 hash errors are not cached and this helps breaks loops with
diff --git a/validator/val_nsec3.h b/validator/val_nsec3.h
index f668a270f..a13e92991 100644
--- a/validator/val_nsec3.h
+++ b/validator/val_nsec3.h
@@ -98,6 +98,12 @@ struct sldns_buffer;
/** The SHA1 hash algorithm for NSEC3 */
#define NSEC3_HASH_SHA1 0x01
+/**
+ * Max number of NSEC3 calculations at once, suspend query for later.
+ * 8 is low enough and allows for cases where multiple proofs are needed.
+ */
+#define MAX_NSEC3_CALCULATIONS 8
+
/**
* Cache table for NSEC3 hashes.
* It keeps a *pointer* to the region its items are allocated.
@@ -19,6 +19,7 @@ SRC_URI = "git://github.com/NLnetLabs/unbound.git;protocol=https;branch=master;t
file://CVE-2026-40622.patch \
file://CVE-2026-41292.patch \
file://CVE-2026-42534.patch \
file://CVE-2026-42923.patch \
"
SRCREV = "f6269baa605d31859f28770e01a24e3677e5f82c"