diff mbox series

[scarthgap,meta-networking,v3] dnsmasq: fix CVE-2026-4890

Message ID 20260721-dnsmasq-cve-2026-4890-v3-1-2cf4e03fa5df@bootlin.com
State New
Headers show
Series [scarthgap,meta-networking,v3] dnsmasq: fix CVE-2026-4890 | expand

Commit Message

Benjamin Robin (Schneider Electric) July 21, 2026, 9:35 a.m. UTC
A Denial of Service (DoS) vulnerability in the DNSSEC validation of
dnsmasq allows remote attackers to cause a denial of service via a
crafted DNS packet.

This patch is used by debian bookworm (2.90-4_deb12u2).
It is also referenced here [1].

[1] https://thekelleys.org.uk/dnsmasq/CVE/CVE-2026-4890.dnsmasq-2.91.diff

Signed-off-by: Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
---
This patch needs to be applied on top of the previous CVE-2026-2291 patch
---
Changes in v3:
- Update patch link (instead of using debian link) to reference:
  https://thekelleys.org.uk/dnsmasq/CVE/CVE-2026-4890.dnsmasq-2.91.diff
- Fix patch, by keeping all whitespace at end of line. Applying this patch
  series is going to generate warnings, but the patch fixing the CVE contained
  in this patch series should apply without any issue.
- Link to v2: https://patch.msgid.link/20260701-dnsmasq-cve-2026-4890-v2-1-76eb4b163c85@bootlin.com

Changes in v2:
- Fix email subject
- Link to v1: https://patch.msgid.link/20260701-dnsmasq-cve-2026-4890-v1-1-9daafc81fde3@bootlin.com
---
 .../recipes-support/dnsmasq/dnsmasq_2.90.bb        |  1 +
 .../dnsmasq/files/CVE-2026-4890.patch              | 75 ++++++++++++++++++++++
 2 files changed, 76 insertions(+)


---
base-commit: 7eb94107580092f79ff1b639a87762fe6f96aa12
change-id: 20260701-dnsmasq-cve-2026-4890-f5b3a76de3ad

Best regards,
--  
Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
diff mbox series

Patch

diff --git a/meta-networking/recipes-support/dnsmasq/dnsmasq_2.90.bb b/meta-networking/recipes-support/dnsmasq/dnsmasq_2.90.bb
index 3a7af56c34d7..ad79a3bfa828 100644
--- a/meta-networking/recipes-support/dnsmasq/dnsmasq_2.90.bb
+++ b/meta-networking/recipes-support/dnsmasq/dnsmasq_2.90.bb
@@ -21,6 +21,7 @@  SRC_URI = "http://www.thekelleys.org.uk/dnsmasq/${@['archive/', ''][float(d.getV
            file://CVE-2026-4893.patch \
            file://CVE-2026-5172.patch \
            file://CVE-2026-2291.patch \
+           file://CVE-2026-4890.patch \
 "
 SRC_URI[sha256sum] = "8f6666b542403b5ee7ccce66ea73a4a51cf19dd49392aaccd37231a2c51b303b"
 
diff --git a/meta-networking/recipes-support/dnsmasq/files/CVE-2026-4890.patch b/meta-networking/recipes-support/dnsmasq/files/CVE-2026-4890.patch
new file mode 100644
index 000000000000..975a80d474b2
--- /dev/null
+++ b/meta-networking/recipes-support/dnsmasq/files/CVE-2026-4890.patch
@@ -0,0 +1,75 @@ 
+From 6a185fdd49ee668c75ad7e95461de45c3a3d8d10 Mon Sep 17 00:00:00 2001
+Author: Simon Kelley <simon@thekelleys.org.uk>
+Date:   Fri Apr 10 22:16:45 2026 +0100
+Subject: [PATCH] Fix NSEC bitmap parsing infinite loop. CVE-2026-4890
+
+Report from Royce M <royce@xchglabs.com>.
+
+Location: dnssec.c:1290-1306, dnssec.c:1450-1463
+
+The bitmap window iteration advances by p[1] instead of p[1]+2 (missing the 2-byte window header). With bitmap_length=0, both rdlen and p are
+unchanged, causing an infinite loop and dnsmasq stops responding to all queries.
+
+The same code accesses p[2] after only checking rdlen >= 2 without verifying p[1] >= 1, causing OOB reads at 6 locations.
+
+Both bugs are reachable before RRSIG validation (confirmed by the source comment at line 2125), so no valid DNSSEC signatures are needed.
+
+CVE: CVE-2026-4890
+Upstream-Status: Backport [https://thekelleys.org.uk/dnsmasq/CVE/CVE-2026-4890.dnsmasq-2.91.diff]
+
+Signed-off-by: Benjamin Robin <benjamin.robin@bootlin.com>
+---
+ src/dnssec.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/dnssec.c b/src/dnssec.c
+index ed2f53ff1763..68f1b5d0fab4 100644
+--- a/src/dnssec.c
++++ b/src/dnssec.c
+@@ -1270,10 +1270,10 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
+ 	     packet checked to be as long as rdlen implies in prove_non_existence() */
+ 	  
+ 	  /* If we can prove that there's no NS record, return that information. */
+-	  if (nons && rdlen >= 2 && p[0] == 0 && (p[2] & (0x80 >> T_NS)) != 0)
++	  if (nons && rdlen >= 2 && p[0] == 0 && p[1] >= 1  && (p[2] & (0x80 >> T_NS)) != 0)
+ 	    *nons = 0;
+ 	  
+-	  if (rdlen >= 2 && p[0] == 0)
++	  if (rdlen >= 2 && p[0] == 0 && p[1] >= 1)
+ 	    {
+ 	      /* A CNAME answer would also be valid, so if there's a CNAME is should 
+ 		 have been returned. */
+@@ -1301,8 +1301,8 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
+ 		  break; /* finished checking */
+ 		}
+ 	      
+-	      rdlen -= p[1];
+-	      p +=  p[1];
++	      rdlen -= p[1] + 2;
++	      p +=  p[1] + 2;
+ 	    }
+ 	  
+ 	  return 0;
+@@ -1429,7 +1429,7 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
+ 		p += hash_len; /* skip next-domain hash */
+ 		rdlen -= p - psave;
+ 
+-		if (rdlen >= 2 && p[0] == 0)
++		if (rdlen >= 2 && p[0] == 0 && p[1] >= 1)
+ 		  {
+ 		    /* If we can prove that there's no NS record, return that information. */
+ 		    if (nons && (p[2] & (0x80 >> T_NS)) != 0)
+@@ -1458,8 +1458,8 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
+ 			break; /* finished checking */
+ 		      }
+ 		    
+-		    rdlen -= p[1];
+-		    p +=  p[1];
++		    rdlen -= p[1] + 2;
++		    p +=  p[1] + 2;
+ 		  }
+ 		
+ 		return 1;
+-- 
+2.55.0
+