Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package dnsmasq for openSUSE:Factory checked 
in at 2026-11-04 19:42:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dnsmasq (Old)
 and      /work/SRC/openSUSE:Factory/.dnsmasq.new.3759290 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "dnsmasq"

Wed Nov  4 19:42:25 2026 rev:109 rq:1394549 version:2.93

Changes:
--------
--- /work/SRC/openSUSE:Factory/dnsmasq/dnsmasq.changes  2026-07-02 
20:07:34.189464629 +0200
+++ /work/SRC/openSUSE:Factory/.dnsmasq.new.3759290/dnsmasq.changes     
2026-11-04 19:42:29.007935968 +0100
@@ -1,0 +2,19 @@
+Fri Oct 30 14:50:00 UTC 2026 - Reinhard Max <[email protected]>
+
+- Add upstream security fixes:
+  * CVE-2026-93006, bsc#1288828: TFTP server can serve the wrong
+    file contents because a recently used transfer cache is not
+    invalidated when a transfer finishes
+    (dnsmasq-CVE-2026-93006.patch).
+  * CVE-2026-93007, bsc#1288829: TCP DNS service uses a small fixed
+    pool of child processes and does not set a receive timeout on
+    client connections (dnsmasq-CVE-2026-93007.patch, partial fix).
+  * CVE-2026-93008, bsc#1288830: Records for the CNAME target were
+    cached without checking that they belong to the responding
+    server's zone (dnsmasq-CVE-2026-93008.patch).
+  * CVE-2026-93009, bsc#1288831: Out-of-bounds read in the DHCPv6
+    FQDN option parser (dnsmasq-CVE-2026-93009.patch).
+  * CVE-2026-93011, bsc#1288833: One-byte heap overflow of a name
+    buffer in the DNSSEC validator (dnsmasq-CVE-2026-93011.patch).
+
+-------------------------------------------------------------------

New:
----
  dnsmasq-CVE-2026-93006.patch
  dnsmasq-CVE-2026-93007.patch
  dnsmasq-CVE-2026-93008.patch
  dnsmasq-CVE-2026-93009.patch
  dnsmasq-CVE-2026-93011.patch

----------(New B)----------
  New:    invalidated when a transfer finishes
    (dnsmasq-CVE-2026-93006.patch).
  * CVE-2026-93007, bsc#1288829: TCP DNS service uses a small fixed
  New:    pool of child processes and does not set a receive timeout on
    client connections (dnsmasq-CVE-2026-93007.patch, partial fix).
  * CVE-2026-93008, bsc#1288830: Records for the CNAME target were
  New:    cached without checking that they belong to the responding
    server's zone (dnsmasq-CVE-2026-93008.patch).
  * CVE-2026-93009, bsc#1288831: Out-of-bounds read in the DHCPv6
  New:  * CVE-2026-93009, bsc#1288831: Out-of-bounds read in the DHCPv6
    FQDN option parser (dnsmasq-CVE-2026-93009.patch).
  * CVE-2026-93011, bsc#1288833: One-byte heap overflow of a name
  New:  * CVE-2026-93011, bsc#1288833: One-byte heap overflow of a name
    buffer in the DNSSEC validator (dnsmasq-CVE-2026-93011.patch).
----------(New E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dnsmasq.spec ++++++
--- /var/tmp/diff_new_pack.HGYm2t/_old  2026-11-04 19:42:30.323991056 +0100
+++ /var/tmp/diff_new_pack.HGYm2t/_new  2026-11-04 19:42:30.325991140 +0100
@@ -40,6 +40,11 @@
 Source5:        rc.dnsmasq-suse
 Source6:        system-user-dnsmasq.conf
 Patch0:         dnsmasq-groups.patch
+Patch1:         dnsmasq-CVE-2026-93006.patch
+Patch2:         dnsmasq-CVE-2026-93007.patch
+Patch3:         dnsmasq-CVE-2026-93008.patch
+Patch4:         dnsmasq-CVE-2026-93009.patch
+Patch5:         dnsmasq-CVE-2026-93011.patch
 BuildRequires:  dbus-1-devel
 BuildRequires:  dos2unix
 BuildRequires:  libnettle-devel
@@ -78,7 +83,9 @@
 server's leases.
 
 %prep
-%autosetup -p0
+%autosetup -N
+%autopatch -p0 -M 0
+%autopatch -p1 -m 1
 
 # Remove the executable bit from python example files to
 # avoid unwanted automatic dependencies


++++++ dnsmasq-CVE-2026-93006.patch ++++++
>From cdbfb972276ca3d07bec9246f57be8cd7c7d5478 Mon Sep 17 00:00:00 2001
From: Simon Kelley <[email protected]>
Date: Fri, 16 Oct 2026 22:33:51 +0100
Subject: [PATCH] Fix logic error in TFTP caching.

The TFTP subsystem prefetches data from disk. If a TFTP transfer
is freed, and a new one allocated the same memory, then previously
prefetched data could be wrongly supplied.

Thanks to Lucas Celant <[email protected]> for spotting this.

CVE-2026-93006 may apply.
---
 src/tftp.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/tftp.c b/src/tftp.c
index 6d5d56d..da8a9ff 100644
--- a/src/tftp.c
+++ b/src/tftp.c
@@ -836,6 +836,12 @@ static void free_transfer(struct tftp_transfer *transfer)
       close(transfer->file->fd);
       free(transfer->file);
     }
+
+  /* freeing this transfer and then allocating a new one
+     may result in the same memory, but the contents of
+     the transfer is no longer valid to cache. */
+  if (daemon->srv_save == transfer)
+    daemon->srv_save = NULL;
   
   free(transfer);
 }
-- 
2.56.0


++++++ dnsmasq-CVE-2026-93007.patch ++++++
>From 11493fe2186f837aeda74e8bf7fae8b92773a498 Mon Sep 17 00:00:00 2001
From: Simon Kelley <[email protected]>
Date: Fri, 16 Oct 2026 20:58:00 +0100
Subject: [PATCH] Improve resistance to many simultaneous TCP connections.

Dnsmasq limits the number of simultaneous TCP connections,
to avoid resource-exhaustion attacks. Once the limit if reached,
dnsmasq stops accepting TCP connections from the kernel.

When doing dnssec validation, the same resources are used to
handle internally generated queries with large answers
needed to validate incoming queries which can still arrive via UDP.
If a dnsmasq daemon has reached the limit on incoming
TCP connections then these queries will fail to validate needlessly.

Bump the number of TCP-process resources by 50% when dnssec validation
is enabled, and reserve the extra 50% only for internally-generated
dnssec validation queries. This allows validation to continue even
when dnsmasq is ignoring new TCP requests.

Thanks to Lucas Celant <[email protected]> for spotting this.

CVE-2026-93007 may apply.
---
 src/dnsmasq.c | 33 ++++++++++++++++++++++++---------
 src/dnsmasq.h |  3 ++-
 2 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index adaa692..3337e01 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -140,6 +140,9 @@ int main (int argc, char **argv)
       /* one char flag per possible RR in answer section (may get extended). */
       daemon->rr_status_sz = 64;
       daemon->rr_status = safe_malloc(sizeof(*daemon->rr_status) * 
daemon->rr_status_sz);
+      /* Increase TCP process slots by half, and reserve the extra for 
validation-to-tcp use only. */
+      daemon->dnssec_tcp_slot_reserved = daemon->max_procs/2;
+      daemon->max_procs += daemon->dnssec_tcp_slot_reserved;
     }
 #endif
   
@@ -427,7 +430,8 @@ int main (int argc, char **argv)
 
       daemon->tcp_pids = safe_malloc(daemon->max_procs*sizeof(pid_t));
       daemon->tcp_pipes = safe_malloc(daemon->max_procs*sizeof(int));
-
+      daemon->tcp_type = safe_malloc(daemon->max_procs);
+      
       for (i = 0; i < daemon->max_procs; i++)
        daemon->tcp_pipes[i] = -1;
     }
@@ -1652,7 +1656,11 @@ static void async_event(int pipe, time_t now)
                  
                  /* tcp_pipes == -1 && tcp_pids == 0 required to free slot */
                  if (daemon->tcp_pipes[i] == -1)
-                   daemon->metrics[METRIC_TCP_CONNECTIONS]--;
+                   {
+                     if (daemon->tcp_type[i])
+                        daemon->dnssec_tcp_slot_reserved++;
+                     daemon->metrics[METRIC_TCP_CONNECTIONS]--;
+                   }
                }
        break;
        
@@ -1888,7 +1896,7 @@ static void set_dns_listeners(void)
   struct serverfd *serverfdp;
   struct listener *listener;
   struct randfd_list *rfl;
-  int i;
+  int i, j;
   
   for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
     poll_listen(serverfdp->fd, POLLIN);
@@ -1902,8 +1910,8 @@ static void set_dns_listeners(void)
     poll_listen(rfl->rfd->fd, POLLIN);
   
   /* check to see if we have free tcp process slots. */
-  for (i = daemon->max_procs - 1; i >= 0; i--)
-    if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
+  for (j = 0, i = daemon->max_procs - 1; i >= 0; i--)
+    if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1 && ++j > 
daemon->dnssec_tcp_slot_reserved)
       break;
 
   for (listener = daemon->listeners; listener; listener = listener->next)
@@ -1930,7 +1938,7 @@ static void check_dns_listeners(time_t now)
   struct serverfd *serverfdp;
   struct listener *listener;
   struct randfd_list *rfl;
-  int i;
+  int i, j;
   
   /* Note that handling events here can create or destroy fds and
      render the result of the last poll() call invalid. Once
@@ -1955,7 +1963,11 @@ static void check_dns_listeners(time_t now)
              daemon->tcp_pipes[i] = -1;        
              /* tcp_pipes == -1 && tcp_pids == 0 required to free slot */
              if (daemon->tcp_pids[i] == 0)
-               daemon->metrics[METRIC_TCP_CONNECTIONS]--;
+               {
+                 daemon->metrics[METRIC_TCP_CONNECTIONS]--;
+                 if (daemon->tcp_type[i])
+                   daemon->dnssec_tcp_slot_reserved++;
+               }
            }
          return;
        }
@@ -1995,8 +2007,8 @@ static void check_dns_listeners(time_t now)
      at least one a poll() time, that we still do.
      There may be more waiting connections after
      poll() returns then free process slots. */
-  for (i = daemon->max_procs - 1; i >= 0; i--)
-    if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
+  for (j = 0,i = daemon->max_procs - 1; i >= 0; i--)
+    if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1 && ++j > 
daemon->dnssec_tcp_slot_reserved)
       break;
 
   if (i >= 0)
@@ -2159,6 +2171,7 @@ static void do_tcp_connection(struct listener *listener, 
time_t now, int slot)
 
          daemon->tcp_pids[slot] = p;
          daemon->tcp_pipes[slot] = pipefd[0];
+         daemon->tcp_type[slot] = 0;
          daemon->metrics[METRIC_TCP_CONNECTIONS]++;
          if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used)
            daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS];
@@ -2280,6 +2293,8 @@ int swap_to_tcp(struct frec *forward, time_t now, int 
status, struct dns_header
          /* i holds index of free slot */
          daemon->tcp_pids[i] = p;
          daemon->tcp_pipes[i] = pipefd[0];
+         daemon->tcp_type[i] = 1;
+         daemon->dnssec_tcp_slot_reserved--;
          daemon->metrics[METRIC_TCP_CONNECTIONS]++;
          if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used)
            daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS];
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index ebb8d15..cad57dd 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1295,6 +1295,7 @@ extern struct daemon {
   int    fd_save;          /*      "        "        */
   pid_t *tcp_pids;
   int *tcp_pipes;
+  char *tcp_type;
   int pipe_to_parent;
   int numrrand;
   struct randfd *randomsocks;
@@ -1354,7 +1355,7 @@ extern struct daemon {
   /* file for packet dumps. */
   int dumpfd;
 #endif
-  int max_procs;
+  int max_procs, dnssec_tcp_slot_reserved;
   uint max_procs_used;
 } *daemon;
 
-- 
2.56.0


++++++ dnsmasq-CVE-2026-93008.patch ++++++
>From 7719737f3687a2e8e98d8ede31e4f1a006f2deea Mon Sep 17 00:00:00 2001
From: Simon Kelley <[email protected]>
Date: Fri, 16 Oct 2026 15:22:23 +0100
Subject: [PATCH] Fix subdomain-test in find_soa()

Do correct subdomain test, rather than a substring match.

Thanks to Lucas Celant <[email protected]> for spotting this.

CVE-2026-93008 may apply.
---
 src/rfc1035.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/rfc1035.c b/src/rfc1035.c
index 16df1b1..bdb0104 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -560,7 +560,7 @@ static int find_soa(struct dns_header *header, size_t qlen, 
char *name, int *sub
          soa_len = strlen(daemon->workspacename);
 
          /* SOA must be for the name we're interested in. */
-         if (soa_len <= name_len && memcmp(daemon->workspacename, name + 
name_len - soa_len, soa_len) == 0)
+         if (hostname_issubdomain(daemon->workspacename, name) != 0)
            {
              int prefix = name_len - soa_len;
              
-- 
2.56.0


++++++ dnsmasq-CVE-2026-93009.patch ++++++
>From a627a7847ffa50eefedfe8cf842522a2c12e36c4 Mon Sep 17 00:00:00 2001
From: Simon Kelley <[email protected]>
Date: Fri, 16 Oct 2026 23:04:00 +0100
Subject: [PATCH] Fix off-by-one bounds check in DHCPv6 FQDN option.

Thanks to Lucas Celant <[email protected]> for spotting this.

CVE-2026-93009 may apply.
---
 src/rfc3315.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/rfc3315.c b/src/rfc3315.c
index 2ac6f86..119be52 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -502,7 +502,7 @@ static int dhcp6_no_relay(struct state *state, int 
msg_type, unsigned char *inbu
  
        state->fqdn_flags &= ~0x04;
 
-       if (len != 0 && len < 255)
+       if (len >= 1 && len < 255)
         {
           unsigned char *pp, *op = opt6_ptr(opt, 1);
           char *pq = daemon->dhcp_buff;
-- 
2.56.0


++++++ dnsmasq-CVE-2026-93011.patch ++++++
>From 145abca7f62a7744fb9aa742ac71e1c10af4cda7 Mon Sep 17 00:00:00 2001
From: Simon Kelley <[email protected]>
Date: Sat, 17 Oct 2026 01:05:16 +0100
Subject: [PATCH] Fix DNS name buffer overflow.

There are a couple of instances in the DNSSEC validation code where
the code steps along a DNS name to remove some number if left-hand
labels and replace them with * to make a wildcard. The name then
gets passed to to_wire() to translate it in-place to the wire format.

If external parameters dictate that all the labels are removed, and the name
is of exactly the maximum size, then this causes to_wire() to overwrite the
buffer by one byte.

Having created the wildcard, move it to the start of the buffer to avoid
this problem.

Thanks to Lucas Celant <[email protected]> for spotting this.

CVE-2026-93011 may apply.
---
 src/dnssec.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/dnssec.c b/src/dnssec.c
index 71c9bac..2102597 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -486,7 +486,6 @@ static int validate_rrset(time_t now, struct dns_header 
*header, size_t plen, in
       int i, wire_len, sig_len;
       const struct nettle_hash *hash;
       void *ctx;
-      char *name_start;
       u32 nsigttl, ttl, orig_ttl;
 
       failflags &= ~DNSSEC_FAIL_NOSIG;
@@ -576,13 +575,13 @@ static int validate_rrset(time_t now, struct dns_header 
*header, size_t plen, in
          if (!extract_name(header, plen, &p, name, EXTR_NAME_EXTRACT, 10)) 
            return STAT_BOGUS;
 
-         name_start = name;
-         
          /* if more labels than in RRsig name, hash *.<no labels in rrsig 
labels field>  4035 5.3.2 */
          /* If the name is already the wildcard, we're not going to change it. 
*/
          if (labels < name_labels &&
-             !(name_labels - labels == 1 && name_start[0] == '*' && 
name_start[1] == '.'))
+             !(name_labels - labels == 1 && name[0] == '*' && name[1] == '.'))
            {
+             char *name_start = name;
+
              for (j = name_labels - labels; j != 0; j--)
                {
                  while (*name_start != '.' && *name_start != 0)
@@ -595,11 +594,13 @@ static int validate_rrset(time_t now, struct dns_header 
*header, size_t plen, in
                *wildcard_offset_out = name_start - name + 1;
              
              name_start--;
-             *name_start = '*';              
+             *name_start = '*';
+             /* move our name to the start of the buffer to avoid pathalogical 
cases over-running the end in to_wire(). */
+             memmove(name, name_start, strlen(name_start) + 1);              
            }
-         
-         wire_len = to_wire(name_start);
-         hash->update(ctx, (unsigned int)wire_len, (unsigned char 
*)name_start);
+
+         wire_len = to_wire(name);
+         hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name);
          hash->update(ctx, 4, p); /* class and type */
          hash->update(ctx, 4, (unsigned char *)&nsigttl);
 
@@ -1687,11 +1688,13 @@ static int prove_non_existence_nsec3(struct dns_header 
*header, size_t plen, uns
       
       wildcard--;
       *wildcard = '*';
+      /* move our name to the start of the buffer to avoid pathalogical cases 
over-running the end in to_wire(). */
+      memmove(name, wildcard, strlen(wildcard) + 1);
       
       if (dec_counter(validate_counter, NULL))
        return DNSSEC_FAIL_WORK;
       
-      if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, 
iterations)) == 0)
+      if ((digest_len = hash_name(name, &digest, hash, salt, salt_len, 
iterations)) == 0)
        return DNSSEC_FAIL_NONSEC;
       
       if (!check_nsec3_coverage(header, plen, digest_len, digest, type, 
workspace1, workspace2, nsecs, nsec_count, NULL, 1))
-- 
2.56.0

Reply via email to