Fixed upstream 1 Oct 2026 Upstream bug fix in dnsmasq
dnsmasq: stale SLAAC name records after a DHCP lease loses its hostname
Our scanner flagged that dnsmasq, the DNS and DHCP server built into many routers and Linux systems, could pass a NULL hostname to a %s log format in its SLAAC code. We sent a small patch to the dnsmasq-discuss mailing list. Author and maintainer Simon Kelley traced it to the underlying cause, SLAAC name records left on a lease that had lost its hostname, and fixed that the next day. His commit message credits Martin Vlach with finding a symptom of it in the SLAAC logging code. A second patch from the same scan, for an allocation-failure bug in poll_listen(), was applied as well.
What was wrong
For DHCPv4 clients on interfaces with router-advertisement naming, dnsmasq derives SLAAC IPv6 addresses from the client’s MAC address and maps them to the lease’s hostname. slaac_add_addrs() creates these records only when the lease has a hostname, and otherwise returned early without touching existing records.
A lease can lose its hostname later, for example when another client claims the same name and kill_name() clears it. Its SLAAC records stayed behind. When an ICMPv6 echo reply for one of those addresses arrived, slaac_ping_reply() logged it with lease->hostname, by then NULL, as a %s argument. That is undefined behaviour in C. glibc and musl print (null), so the visible symptom is cosmetic there, but the name-to-address data derived from the old hostname was no longer valid either way.
How it was fixed
Our patch only guarded the log line, printing * for a missing name as lease.c already does. Simon Kelley fixed the cause instead: kill_name() now removes the lease’s SLAAC records, lease_set_hostname() regenerates them when a name is added, and slaac_add_addrs() always drops the old records before deciding whether to create new ones.
lease->hostname = lease->fqdn = NULL;
+
+#ifdef HAVE_DHCP6
+ /* A lease which had a hostname when slaac_add_addrs() was called on it
+ may have slaac-address records. Since it no longer has a hostname,
+ they are no-longer valid, so update to remove them */
+ slaac_add_addrs(lease, 0, 0);
+#endif
}
A second patch from the same scan
The same run flagged poll_listen() in src/poll.c. When the pollfds array has to grow, the old code doubled arrsize before calling whine_realloc(). If that allocation failed, arrsize stayed doubled while the array kept its old size. The next call skipped the extension and wrote past the end of the array, or through NULL if the very first allocation had failed, and the state stayed broken until dnsmasq restarted. It only matters once memory allocation fails, so it is a robustness fix, not something an attacker can trigger directly. Our three-line patch updates arrsize only after the reallocation succeeds. Simon Kelley committed it on 1 Oct as baeb743 and replied “Patch applied.” on the list on 11 Oct.
Timeline
- 30 Sep 2026. A scan of the dnsmasq tree (59 files, model qwen3.8-27b) flagged the NULL hostname in
slaac_ping_reply(); six triage rounds rated it valid. We found the path by reading the code, without reproducing it, and mailed a patch to dnsmasq-discuss the same evening, together with thepoll_listen()patch from the same run. - 1 Oct. Simon Kelley committed “Clear down SLAAC-name data when a DHCP lease loses its hostname.” He also committed our
poll_listen()patch as baeb743. - 11 Oct. On the list he replied to the SLAAC patch, “This is definitely a real problem”, explaining that the AAAA record also has to change when the name moves and that commit 03fd0c1 addresses all the issues. He answered the
poll_listen()patch with “Patch applied.” As of 12 Oct 2026 neither commit is in a tagged release yet; the latest release is 2.93.
How to read this
The scanner found a symptom; the maintainer found the cause. Our patch would have quieted one log line, while the upstream fix removes the stale records that made it possible. A narrow patch is a starting point for the maintainer, not the final word. Findings are leads for people, not verdicts.