Fix improper validated wire format of DNS name

Ensure extract_name stops whenever name is longer than 255 bytes. That
is defined by RFC 1035 and MAXDNAME is derived from that length. Dnsmasq
until now relied on upstream servers filtering similar responses to be
filtered out.

Stop immediately if the packet is big enough, but binary name length
exceeds 255 bytes. That is prerequisite for escaped name to become
longer than existing buffer long MAXDNAME. Introduce new MAXWNAME
constant for on-wire length limit. MAXDNAME remains escaped
"presentation" format limit, possibly containing IDN or escaping.
Standard escaping is \ddd, where ddd are decadic value of that byte.
Such escaping is not implemented by dnsmasq. MAXDNAME should be large
enough for any escaped names as long as MAXWNAME cannot exceed defined
length.

Signed-off-by: Petr Menšík <pemensik@redhat.com>
Resolves-Vulnerability: CVE-2026-2291
Resolves: RHEL-181040
This commit is contained in:
Petr Menšík 2026-03-18 19:40:19 +01:00
parent d4dd3b7f9a
commit 1d62ca52b7
2 changed files with 103 additions and 1 deletions

View File

@ -0,0 +1,95 @@
From 74b2a7d33baa96761c14433671916c1c153d6017 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
Date: Tue, 24 Feb 2026 20:36:04 +0100
Subject: [PATCH] Fix improper validated wire format of DNS name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Ensure extract_name stops whenever name is longer than 255 bytes. That
is defined by RFC 1035 and MAXDNAME is derived from that length. Dnsmasq
until now relied on upstream servers filtering similar responses to be
filtered out.
Stop immediately if the packet is big enough, but binary name length
exceeds 255 bytes. That is prerequisite for escaped name to become
longer than existing buffer long MAXDNAME. Introduce new MAXWNAME
constant for on-wire length limit. MAXDNAME remains escaped
"presentation" format limit, possibly containing IDN or escaping.
Standard escaping is \ddd, where ddd are decadic value of that byte.
Such escaping is not implemented by dnsmasq. MAXDNAME should be large
enough for any escaped names as long as MAXWNAME cannot exceed defined
length.
Signed-off-by: Petr Menšík <pemensik@redhat.com>
---
src/dns-protocol.h | 1 +
src/rfc1035.c | 2 +-
src/rrfilter.c | 14 ++++++++++----
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/dns-protocol.h b/src/dns-protocol.h
index e71bedc4..8103b558 100644
--- a/src/dns-protocol.h
+++ b/src/dns-protocol.h
@@ -23,6 +23,7 @@
#define INADDRSZ 4
#define PACKETSZ 512 /* maximum packet size */
+#define MAXWNAME 255 /* maximum on-wire domain name */
#define MAXDNAME 1025 /* maximum presentation domain name */
#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */
#define MAXLABEL 63 /* maximum length of domain label */
diff --git a/src/rfc1035.c b/src/rfc1035.c
index f0e10822..bea30380 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -109,7 +109,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
else if (label_type == 0x00)
{ /* label_type = 0 -> label. */
namelen += l + 1; /* include period */
- if (namelen >= MAXDNAME)
+ if (namelen > MAXWNAME)
return 0;
if (!CHECK_LEN(header, p, plen, l))
return 0;
diff --git a/src/rrfilter.c b/src/rrfilter.c
index 29f69c74..b8093cf5 100644
--- a/src/rrfilter.c
+++ b/src/rrfilter.c
@@ -23,6 +23,7 @@
static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
{
unsigned char *ansp = *namep;
+ unsigned int namelen = 0;
while(1)
{
@@ -84,15 +85,20 @@ static int check_name(unsigned char **namep, struct dns_header *header, size_t p
count = *(ansp++); /* Bits in bitstring */
if (count == 0) /* count == 0 means 256 bits */
- ansp += 32;
+ count = 32;
else
- ansp += ((count-1)>>3)+1;
+ count = ((count-1)>>3)+1;
+ namelen += count + 1;
+ if (namelen > MAXWNAME)
+ return 0;
+ ansp += count;
}
else
{ /* label type == 0 Bottom six bits is length */
unsigned int len = (*ansp++) & 0x3f;
-
- if (!ADD_RDLEN(header, ansp, plen, len))
+
+ namelen += len + 1;
+ if (!ADD_RDLEN(header, ansp, plen, len) || namelen > MAXWNAME)
return 0;
if (len == 0)
--
2.53.0

View File

@ -20,7 +20,7 @@
Name: dnsmasq
Version: 2.85
Release: 19%{?extraversion:.%{extraversion}}%{?dist}
Release: 20%{?extraversion:.%{extraversion}}%{?dist}
Summary: A lightweight DHCP/caching DNS server
License: GPLv2 or GPLv3
@ -84,6 +84,10 @@ Patch21: dnsmasq-2.93-CVE-2026-4890.patch
Patch22: dnsmasq-2.93-CVE-2026-4891.patch
Patch23: dnsmasq-2.93-CVE-2026-4892.patch
Patch24: dnsmasq-2.93-CVE-2026-4893.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2439088
# downstream addition to upstream fix
Patch25: dnsmasq-CVE-2026-2291.patch
# This is workaround to nettle bug #1549190
# https://bugzilla.redhat.com/show_bug.cgi?id=1549190
@ -231,6 +235,9 @@ install -Dpm 644 %{SOURCE5} %{buildroot}%{_tmpfilesdir}/%{name}.conf
%{_mandir}/man1/dhcp_*
%changelog
* Fri Jun 05 2026 Petr Menšík <pemensik@redhat.com> - 2.85-20
- Prevent using too long names in downstream change (CVE-2026-2291)
* Tue May 05 2026 Petr Menšík <pemensik@redhat.com> - 2.85-19
- Prevent overflow in extract_name function (CVE-2026-2291)
- Prevent DoS in DNSSEC validation (CVE-2026-4890)