Update embedded dnsmasq to v2.93rc1#2890
Conversation
A malformed DHCP request can cause out-bounds memory reads, and probably SEGV. Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
…ions. A general rewrite and consolidation of the code that determines if an incoming TCP connection is allowed, based on --address and --interface. This was prompted by a bug found by Sławomir Zborowski where a TCP connection for a valid IPv4 address on one interface which arrived via a second interface which didn't have an IPv4 address would be wrongly rejected. Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
These can't be held forever by a client that opens a connection and then sends nothing, but we can still be DoSsed by a server which accepts a connection and never replies. If the TCP process times out, it sends that information to the parent so that the UDP query can be unblocked. As the TCP timeout is 150s it's highly unlikely that any client will still be waiting, but the point is to free resources. Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
If we have a wildcard record *.example.com and recieve a query for a.example.com then that's OK, but we have to check that there isn't an actual a.example.com record. The corner case is when we get a query for *.example.com in that case the non-existence check is not required, but was being done. Thanks to Jan Breig for spotting this. Signed-off-by: Dominik <dl6er@dl6er.de>
FreeBSD 15.0 has added Linux-compatible inotify support, so enable it by looking if the version matches. Since FreeBSD inotify has seen a few bug fixes in 2025H2, so only enable it if __FreeBSD_version >= 1500068. The latter can be checked through osreldate.h or sys/param.h; the latter defines more macros that clash with dnsmasq's, such as MIN and MAX, so use the former. Signed-off-by: Dominik <dl6er@dl6er.de>
The presence of wrong RRSIG RRs in replies causes DNSSEC validation to fail even when the RRs do not require validation because the zone is unsigned. This patch solves the problem and tidies up the logic. Included is some fixes for hostname_issubdomain() which suffered some confusions about argument order :) I've clarified that and checked every to the function to make sure they are using the correct argument order. Note that, at the time of this commit, Google DNS appears to have the same bug, so if you're using 8.8.8.8 or friends as upstream, resolving the broken zones (eg rivcoed.org) will still fail. Thanks to Petr Menšík for the bug report. Signed-off-by: Dominik <dl6er@dl6er.de>
This may be useful for embedded systems for example: log-queries without only_failed places a heavy load on the NAND flash memory. At the same time, logging requests is necessary to troubleshoot network issues. Signed-off-by: Dominik <dl6er@dl6er.de>
If we're doing DNSSEC validation and fail because the upstream reply to our query is SERVFAIL, log this as the reason in validation result line. This will make maintainers lives easier when they get reports of "wrong" validation failure, which is sometimes an upstream problem. Signed-off-by: Dominik <dl6er@dl6er.de>
A CNAME reply to a DNSSEC query was confusing the validation logic. It now accepts a signed CNAME reply to a DS query as proof that no DS exists at the domain. This fixes the DS/zone break detection logic. Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
This was functionally correct, but every call malloced a new buffer and freed the previous one, rather than only doing that when the buffer needed expansion. Signed-off-by: Dominik <dl6er@dl6er.de>
Log all blocks malloced and all blocks freed. Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
This fixes the plethora of 64k buffers that got allocated when doing DNSSEC over TCP. By using the UDP buffer is pass the query into tcp_talk() and allowing tcp_talk to allocate its output buffer one the size of the reply is known, we only need to allocate as much memory as is required. The final reply to the TCP query still needs the 64k buffer because answer_request() and answer_auth() are not capable of extending their output buffers. Signed-off-by: Dominik <dl6er@dl6er.de>
In the DNS TCP code, there are a couple of places where we have a buffer containing a message which we need to send via TCP. The DNS protocol is that this is sent as <16-bit length in network order><message> Making two write calls, one for the length and one for the message causes the TCP stack to send two packets, one for each. A single packet containing both is preferable from a performance POV. Implement a scatter-gather version of our read_write() wrapper and use it where necessary to send TCP DNS messages. Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
…p of free/strdup Signed-off-by: Dominik <dl6er@dl6er.de>
This almost certainly never worked and was never use, and it's rendered obsolete in RFC 9915. Signed-off-by: Dominik <dl6er@dl6er.de>
Anything sent by a client must be multicast. A relay can unicast to a server. Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
While this won't do harm on systems that do 2's completement, it triggers the compilers' undefined-behavior sanitizer and fixes sanitizer error such as the one below (where the 1694... will vary) and is distracting while debugging. dnssec.c:1427:12: runtime error: left shift of 1694604366 by 1 places cannot be represented in type 'int' Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
If iovcnt is exhausted and the first vector element's operation is satisfied, the while loop will read past the end of the iovec array. This triggers the address sanitizer and leads to undefined program state. Avoid reading too far. Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
Signed-off-by: Dominik <dl6er@dl6er.de>
After copying the 128-byte DHCP file field into dhcp_buff2, the sentinel was written to index 129 instead of 128. The byte at index 128 was therefore left holding stale data from the previous DHCP exchange, so a client that fills the entire file field with non-NUL bytes would produce a 129-character netid tag whose last byte is heap garbage. In theory this allows incorrect netid-tag matching; in practice it requires the client to know the heap state of a prior transaction and BOOTP use is uncommon. Security: very-low-severity heap-content exposure that could influence DHCP option selection via tag mismatch; no memory corruption or crash. Signed-off-by: Dominik <dl6er@dl6er.de>
…ME decoder In option_string(), the RFC1035-name label decoder sets i = l (the position past the current label) and then reads val[i] to decide whether to append a '.' separator — but without first checking that i < opt_len. If the last label ends exactly at the option boundary (no NUL terminator), i == opt_len and val[i] reads one byte beyond the option data. The read lands inside the packet buffer so no crash occurs, but the out-of-bounds byte (typically the next DHCPv6 option's type field) could produce a spurious trailing '.' in --log-dhcp output when a client sends a domain-search/nis-domain option without a trailing NUL. Security: OOB read of 1 byte from a network-supplied DHCPv6 packet; reachable only with --log-dhcp enabled; no memory corruption, crash, or meaningful information disclosure. Signed-off-by: Dominik <dl6er@dl6er.de>
Two decoders in option_string() read beyond the end of the supplied option-value buffer when a malformed DHCPv6 option is received: 1. OT_RFC1035_NAME: after advancing i past the last label (i = l), val[i] was read at line 885 to decide whether to append a '.'. If the label ends exactly at opt_len, i == opt_len and val[i] is one byte past the option data. Fixed by guarding with i < opt_len before the read. 2. OT_CSTRING: the loop opened with while(1) and called GETSHORT (a 2-byte read) before checking that two bytes remained, so a 1- or 0-byte option value caused an immediate 1-byte OOB read. Additionally, if the length field exceeded the remaining option data the inner body-copy loop read past the end. Fixed by changing the loop condition to while(i+2 <= opt_len) and adding a check that the body fits before copying. Both reads land inside the received packet buffer (no crash), but they allow a DHCPv6 client to cause dnsmasq to read unrelated packet bytes and emit them in syslog output. Security: OOB reads of up to option-length bytes from a network-supplied DHCPv6 packet; reachable only with --log-dhcp enabled; no memory corruption, crash, or sensitive data disclosure beyond adjacent packet bytes. Signed-off-by: Dominik <dl6er@dl6er.de>
…CODE In log6_opts(), the OPTION6_STATUS_CODE branch did: memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2); daemon->namebuff[len + opt6_len(opt) - 2] = 0; Two bugs: 1. Integer underflow: if opt6_len(opt) < 2, the subtraction wraps to a huge size_t, making memcpy write gigabytes and crash with SIGSEGV. 2. Heap overflow: no upper-bound check. opt6_len() can return up to 65535, but daemon->namebuff is only (MAXDNAME*2)+1 = 2051 bytes. A STATUS_CODE payload larger than ~2045 bytes would overflow the heap buffer. Exploitability: log6_opts() is only ever called on daemon->outpacket, the outgoing DHCPv6 reply built by dnsmasq itself — NOT on incoming client packets. Consequently, these bugs are NOT directly triggerable by a remote attacker under the current code. The fix is defensive: put_opt6_short() (which writes STATUS_CODE options in outgoing packets) always produces opt6_len >= 2, so neither bug fires in practice today. However, the unchecked arithmetic is a latent hazard that could become exploitable if future refactoring passes incoming option data through log6_opts(): - Guard the block with opt6_len(opt) >= 2 to prevent underflow. - Cap slen to the remaining space in daemon->namebuff. Signed-off-by: Dominik <dl6er@dl6er.de>
The EDNS0 option iteration loop read a 2-byte len field from the packet and used it directly in: opt.scope_netmask = p[3]; // requires len >= 4 memcmp(p, &opt, len) // reads len bytes from packet Neither access was guarded against len exceeding the remaining RDATA. A crafted DNS reply whose OPT RDATA contains a CLIENT_SUBNET option with an oversized len field would cause memcmp to read past the end of the packet buffer, leaking heap memory. Risk: currently the only caller that reaches this branch is forward.c:process_reply(), which (before the companion fix) passed an OPT-RR-scoped plen that made skip_name() return NULL first, so the unsafe code was never reached. With that companion fix applied the path is live: a rogue upstream server or on-path attacker can craft a reply with a malformed CLIENT_SUBNET len and trigger the OOB read, potentially leaking adjacent heap contents. Fix: break out of the loop if the option body would extend past the RDATA boundary. Signed-off-by: Dominik <dl6er@dl6er.de>
parse_hex() returns -1 on malformed input. Three call sites in
read_leases() used the return value directly as a length argument
without checking for the error sentinel:
opt_len → lease_set_vendorclass() / lease_set_agent_id()
whine_malloc(-1) attempts a ~4 GB allocation, likely
crashing the process.
hw_len → lease_set_hwaddr()
memcpy(lease->hwaddr, hwaddr, (size_t)-1) performs an
~18 EB write, causing an immediate crash.
clid_len → lease_set_hwaddr() (same path as hw_len)
Exploitation requires a corrupted or attacker-controlled lease file;
it is not directly network-triggerable. However, any process that can
write to the lease file (e.g. a compromised helper) can crash or
potentially gain code execution in the dnsmasq process at next startup
or lease-file re-read.
Fix: mirror the existing duid path (which already guards its
parse_hex call) by checking for < 0. For opt_len, skip the record
(continue) to match the "invalid line" behaviour. For hw_len and
clid_len, treat the failure as a zero-length field so the lease is
still created with the correct address.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
strncat(dst, src, n) truncates src to n bytes, but n should be the remaining space in dst, not the total buffer size. Passing MAXDNAME as n allowed the combined prefix + address + "." + domain to overflow the MAXDNAME-byte namebuff if c->domain was close to MAXDNAME chars. Replace MAXDNAME with MAXDNAME - strlen(name) - 1 at each call site (lines 178-179 for IPv4, 204 for the IPv6 hex-fragment loop, 208-209 for the IPv6 suffix) so the append is always bounded by actual remaining capacity. Security implications: strncat(name, c->domain, MAXDNAME) passes the full buffer size instead of remaining space. Overflow requires a local admin to configure a --synth-domain with a domain name > ~960 chars. The actual exploitable window is narrow: the admin would need a --synth-domain with a domain name close to 1024 chars (which check_name permits) combined with a non-trivial prefix or IPv6 address. Not remotely exploitable. Signed-off-by: Dominik <dl6er@dl6er.de>
When --dump-file points to an existing pcap file, dump_init_file() counts the existing records by reading each pcap record header and seeking past the payload. The lseek() return value was not checked: if it fails (e.g. EOVERFLOW on a 32-bit build with a very large incl_len, or any other seek error) the file position does not advance, the next read_write() call reads the same header again, and the loop spins forever — hanging daemon startup. Fix: break out of the loop on lseek failure. An undercount of existing records is harmless; a hanging startup is not. Signed-off-by: Dominik <dl6er@dl6er.de>
This is the stable release fix for CVE-2026-2291 Dnsmasq recieves and sends domain names within DNS packets in RFC-1035 format, a string of counted labels terminated by a zero length label. Internally to dnsmasq, domain names are represented as zero-terminated C strings with the labels seperated by '.' characters, like the normal presentation format for domain names. The RFC-1035 limit for a domain name in wire format is 255 octets, and when converted to presentation format, this makes a string of maximum 253 characters. However dnsmasq needs to be able to represent any 8-bit character within a label, and this causes problems with /000 (which would terminate the c-string early) and '.' (which would terminate a label early). To avoid this, dnsmasq escapes both of these characters, which means that they take two bytes in the string. The domain name with must charaters in it has four labels and the 255 octet wire length limits these four labels to a total of 250 characters. The other five octets are the four label length bytes and the zero length byte terminator. If all 250 characters need escaping that makes the maximum length of the dnsmasq internal format 503 characters (250 escaped characters in labels, amd three dots between four labels) Since this format is zero-terminated c-string, buffers have to be allocated as 504 bytes. This arrangement grew in a somewhat ad-hoc manner and early dnsmasq didn't do the escaping trick, and didn't really differentiate between the lengths of the wire format and the presentation format, since they were very similar. It also, for reasons lost in time, inherited a defintion for MAXDNAME from early BIND headers, set at 1025 bytes. This value was used as the buffer size for both wire and presentation formats. This patch makes everything consistent. It declares two constants MAXDNAME 255 /* max size of wire format domain name */ MAXDNAMESTR 503 /* max size of internal format created from a 255 octet wire format name */ All internal name buffers are allocated as MAXDNAMESTR+1 bytes, to hold a maximum size internal format name and zero termination. Names parsed out of incoming packets are rejected if their wire format is greater than 255 bytes, which ensures that their internal representation cannot exceed 503 characters. Names inserted into outgoing packets are failed similarly if they exceed 255 bytes. (this would in theory be possible for a legal internal-representaion name if it has at least one unescaped character in a label.
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. Bug is reachable before RRSIG validation (confirmed by the source comment at line 2125), so no valid DNSSEC signatures are needed.
Bug report from Royce M <royce@xchglabs.com> This avoids crafted packets which give a value for rdlen _less_ then the space taken up by the fixed data and the signer's name and engender a negative calculated length for the signature.
Bug reported bt Royce M <royce@xchglabs.com>
Location: helper.c:265-270
DHCPv6 CLIDs can be up to 65535 bytes. When --dhcp-script is configured,
the helper hex-encodes raw CLID bytes via sprintf("%.2x") into daemon->packet (5131 bytes).
A 1000-byte CLID writes ~3000 bytes. The helper process retains root privileges.
Note: log6_packet() correctly caps CLID to 100 bytes for logging, but the helper code path was missed.
Bug report from Royce M <royce@xchglabs.com> Location: forward.c:713, edns0.c:421 With --add-subnet enabled, process_reply() passes the OPT record length (~23 bytes) instead of the packet length to check_source(). All internal bounds checks fail, and the function always returns 1. ECS source validation per RFC 7871 Section 9.2 is completely bypassed.
Thanks to Hugo Martinez Ray for spotting this. The value of rdlen for an RR can be a lie, allowing the call to extract_name() at rfc1025.c:952 to advance the value of p1 past the calculated end of the record. The makes the calculation of bytes remaining in the RR underflow to a huge number and results in a massive heap OOB read and certain crash.
…7fce5b70f0fec25f722f67
Thanks to Royce M <royce@xchglabs.com> for spotting this.
In find_soa() extract_name() is called with extrabytes=0 when parsing NS record names, which means it only validates that the DNS name fits within the packet but does not check that 10 additional bytes exist for the type/class/TTL/rdlen fixed fields. Lines 546-549 then unconditionally read these 10 bytes via GETSHORT/GETLONG macros. An attacker controlling a DNS zone can craft a NXDOMAIN response where the NS record name extends to the packet boundary, causing a 10-byte out-of-bounds read past the valid packet data (CWE-125, CVSS 5.3 Medium). The read stays within the over-allocated packet buffer in default configurations, limiting crash risk, but accesses data outside the logical packet boundary. Under certain conditions, the overread may access stale heap data from prior transactions. The fix is straightforward: change the extrabytes argument from 0 to 10, consistent with other call sites in the same file. Credit is due to do litli for finding this problem.
Signed-off-by: Dominik <dl6er@dl6er.de>
# Conflicts: # CMakeLists.txt # src/dnsmasq/dnsmasq.h # src/dnsmasq/dnssec.c
There was a problem hiding this comment.
Pull request overview
This PR updates the embedded dnsmasq tree to pi-hole-v2.93rc1, bringing in multiple upstream security fixes (several CVEs), DNSSEC correctness improvements, DHCP/inotify fixes, and a set of Pi-hole-specific hardening changes. It also updates FTL glue/build/test code to accommodate the newer dnsmasq and newer nettle digest APIs.
Changes:
- Bump embedded dnsmasq to
v2.93rc1and incorporate upstream DNSSEC/DHCP/inotify changes plus Pi-hole patches. - Adjust FTL + build tooling for updated dependency APIs (notably nettle digest prototype changes) and add a debug build-type toggle in
build.sh. - Update tests and warning allow-lists to match updated dnsmasq log strings.
Reviewed changes
Copilot reviewed 58 out of 58 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| CMakeLists.txt | Bumps embedded dnsmasq version reference to pi-hole-v2.93rc1. |
| build.sh | Forces -DCMAKE_BUILD_TYPE=Debug when using debug mode. |
| src/CMakeLists.txt | Adds CMake configure-time logging for optional crypto/IDN libraries. |
| src/FTL.h | Protects system headers from macro redefinitions (push/pop free/strdup). |
| src/api/2fa.c | Updates nettle HMAC digest call for nettle v4+ API. |
| src/config/password.c | Updates nettle SHA256 digest calls for nettle v4+ API. |
| src/files.c | Updates SHA256 digest call for nettle v4+ API; adds nettle version header include. |
| src/dnsmasq/arp.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/auth.c | Embedded dnsmasq authoritative-answer logic tweaks (offset handling, NS/SOA building). |
| src/dnsmasq/bpf.c | Embedded dnsmasq update: BSD ARP enumeration improvements incl. IPv6 handling. |
| src/dnsmasq/blockdata.c | Embedded dnsmasq update: safer realloc usage for internal scratch buffer. |
| src/dnsmasq/cache.c | Embedded dnsmasq update: cache/hosts name storage and allocation tracking refactor. |
| src/dnsmasq/config.h | Embedded dnsmasq update: constants/macros updates (incl. HAVE_INOTIFY for FreeBSD 15+). |
| src/dnsmasq/conntrack.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/crypto.c | Embedded dnsmasq update: nettle digest API wrapper + realloc fixes. |
| src/dnsmasq/dbus.c | Embedded dnsmasq update: buffer size constant updates. |
| src/dnsmasq/dhcp-common.c | Embedded dnsmasq update: bounds checks in DHCP option decoding + buffer size constant updates. |
| src/dnsmasq/dhcp-protocol.h | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/dhcp.c | Embedded dnsmasq update: minor control-flow fix + buffer size constant updates. |
| src/dnsmasq/dhcp6-protocol.h | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/dhcp6.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/dns-protocol.h | Embedded dnsmasq update: redefine MAXDNAME/MAXDNAMESTR and add EDE code. |
| src/dnsmasq/dnsmasq.c | Embedded dnsmasq update: inotify init timing, DS duplicate handling, DNSSEC TCP timeout plumbing. |
| src/dnsmasq/dnsmasq.h | Embedded dnsmasq update: new options/events/constants, malloc logging, signature changes. |
| src/dnsmasq/dnssec.c | Embedded dnsmasq update: multiple DNSSEC validation correctness and robustness improvements. |
| src/dnsmasq/domain-match.c | Embedded dnsmasq update: guard qsort() when serverarray is NULL. |
| src/dnsmasq/domain.c | Embedded dnsmasq update: string length fixes and safer concatenation sizing. |
| src/dnsmasq/dump.c | Embedded dnsmasq update: check lseek() during pcap record counting. |
| src/dnsmasq/edns0.c | Embedded dnsmasq update: option-length bounds check in check_source(). |
| src/dnsmasq/files.c | Embedded dnsmasq update: (via other files) buffer size constant updates. |
| src/dnsmasq/forward.c | Embedded dnsmasq update: DNSSEC validation retry logic, TCP refactor, new warning, and EDE remapping. |
| src/dnsmasq/helper.c | Embedded dnsmasq update: buffer sizing and bounds checks in helper extradata parsing. |
| src/dnsmasq/inotify.c | Embedded dnsmasq update: error reporting via event pipe + init signature change. |
| src/dnsmasq/ip6addr.h | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/lease.c | Embedded dnsmasq update: parse_hex return checks and buffer size macro update. |
| src/dnsmasq/log.c | Embedded dnsmasq update: preserve existing log file mode while ensuring group-writable. |
| src/dnsmasq/loop.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/metrics.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/metrics.h | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/netlink.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/network.c | Embedded dnsmasq update: buffer size macro alignment and minor comment tweak. |
| src/dnsmasq/nftset.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/option.c | Embedded dnsmasq update: new options + DHCP vendor/user class parsing updates. |
| src/dnsmasq/outpacket.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/pattern.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/poll.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/radv-protocol.h | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/radv.c | Embedded dnsmasq update: buffer size macro updates and bounds logic. |
| src/dnsmasq/rfc1035.c | Embedded dnsmasq update: name extraction hardening + bounds checks and function signature update. |
| src/dnsmasq/rfc2131.c | Embedded dnsmasq update: DHCP logging buffer size update + off-by-one fix + memset fix. |
| src/dnsmasq/rfc3315.c | Embedded dnsmasq update: DHCPv6 relay behavior fixes and multiple bounds/correctness updates. |
| src/dnsmasq/rrfilter.c | Embedded dnsmasq update: workspace expansion refactor and escape handling adjustments. |
| src/dnsmasq/slaac.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/tftp.c | Embedded dnsmasq update: safer string operations and traversal check improvements. |
| src/dnsmasq/ubus.c | Embedded dnsmasq update (copyright year bump). |
| src/dnsmasq/util.c | Embedded dnsmasq update: name-length checks, safer copy semantics, read/writev refactor, malloc logging hooks. |
| test/dnsmasq_warnings | Updates expected warning strings for the updated dnsmasq log messages. |
| test/test_final.bats | Updates warning allowlist regex for updated DNSSEC warning wording/casing. |
| test/zone_update.py | Makes the zone-update test utility configurable via CLI args (proto/port/server). |
Comments suppressed due to low confidence (1)
test/zone_update.py:37
- The UDP/TCP branches use tab indentation, and the script no longer handles invalid
protovalues (it will silently do nothing). Since this is used from the test suite, it would be safer to use consistent spaces for indentation and to restore anelsethat prints an error and exits non-zero whenprotois notudportcp.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Usage: python3 zone_update.py [proto = tcp] [port = 5300] [server = 127.0.0.1] | ||
|
|
||
| # Get the protocol, server, and port from command line arguments or use defaults | ||
| proto = sys.argv[1] if len(sys.argv) > 1 else 'tcp' | ||
| port = int(sys.argv[2]) if len(sys.argv) > 2 else 53 | ||
| server = sys.argv[3] if len(sys.argv) > 3 else '127.0.0.1' |
| // TOTP+HMAC | ||
| #include <nettle/hmac.h> | ||
| #include <nettle/sha1.h> | ||
|
|
||
| static uint32_t hotp(const uint8_t *key, size_t key_len, const uint64_t counter, const uint8_t digits) | ||
| { | ||
| // Initialize HMAC-SHA1 (RFC 2104) | ||
| // TOTP uses HMAC-SHA1 (RFC 6238, section 5.1) | ||
| struct hmac_sha1_ctx ctx; | ||
| hmac_sha1_set_key(&ctx, key_len, key); | ||
|
|
||
| // Convert counter to big endian | ||
| const uint64_t counter_be = htobe64(counter); | ||
|
|
||
| // Compute HMAC-SHA1 | ||
| hmac_sha1_update(&ctx, sizeof(counter_be), (uint8_t*)&counter_be); | ||
| uint8_t out[SHA1_DIGEST_SIZE]; | ||
| #if NETTLE_VERSION_MAJOR >= 4 | ||
| hmac_sha1_digest(&ctx, out); | ||
| #else | ||
| hmac_sha1_digest(&ctx, SHA1_DIGEST_SIZE, out); | ||
|
|
||
| #endif |
| { | ||
| new->len = parse_hex(comma, (unsigned char *)arg, strlen(arg), NULL, NULL); | ||
| new->data = opt_malloc(new->len); | ||
| memcpy(new->data, arg, new->len); | ||
| } |
| /* length of final label and terminaton added */ | ||
| if (!idn_encode && wiresize + dotgap + 2 > MAXDNAME) | ||
| return 0; /* wire representation too long */ |
|
|
||
| /* IDN library doesnt call our malloc wrapper, so log this by steam */ | ||
| if (ret) | ||
| malloc_log(ret, strlen(ret)+1); |
| /* Dnsmasq handles domains names internally as NULL-terminated C strings. | ||
| The '.' characters in these strings are significant as label-seperators. | ||
| '.' and /0 characters _within_ labels are escaped and take up two | ||
| characters to allow labels to contain arbitrary characters. | ||
|
|
||
| The maximum length of a domain name in wire format is 255 bytes. | ||
| and the maximum length of this when coverted to a <label>.<label> string | ||
| is 253 characters. Reasoning: the wire format representation of a | ||
| label is one byte length followed by up to length characters so each of | ||
| these labels except the last takes the same space since the length is | ||
| replaced by the '.' seperator. | ||
| The last label doesn't have the "." so it takes one less character |
| characters to allow labels to contain arbitrary characters. | ||
|
|
||
| The maximum length of a domain name in wire format is 255 bytes. | ||
| and the maximum length of this when coverted to a <label>.<label> string |
| 503 characters. | ||
| */ | ||
| #define MAXDNAME 255 /* Maximum size of a domain name in wire format */ | ||
| #define MAXDNAMESTR 503 /* Maximum size of dnsmasq c-string representaion of a domain name. */ |
|
Master received v2.92.2 which is only few targetted patches on top of the older v2.92. This has all the v2.93 code in it (many more but not as critical fixes). |
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
What does this implement/fix?
Update embedded dnsmasq to v2.93rc1
Highlights
Security
(all of these have already been merged into
masterand are released separately)rdlen.--add-subnet.extract_addresses()via crafted RRrdlen.DNSSEC correctness
DHCP and inotify
Further fixes and improvements made by the Pi-hole team
dump: checklseek()return in pcap record-counting loop.domain: fixstrncatbuffer-size argument inis_rev_synth().lease: checkparse_hex()return value before use as length.edns0: bounds-check option length beforememcmpincheck_source().rfc3315: fix integer underflow / heap overflow inlog6_opts STATUS_CODE.dhcp-common: fix OOB reads in DHCPv6option_string()decoders.dhcp-common: bounds-check label index before reading inOT_RFC1035_NAMEdecoder.rfc2131: fix off-by-one in BOOTP filename netid NUL termination.helper: fix OOB read ingrab_extradata_luabounds check.prettyprint_time(): NUL-terminate buf whent == 0.rand64()must share globaloutleftwithrand16()/rand32().reply_query(): move fd-match guard out of loop.expand_workspace_real(): zero the correct byte count.Related issue or feature (if applicable): N/A
Pull request in docs with documentation (if applicable): N/A
By submitting this pull request, I confirm the following:
git rebase)Checklist:
developmentbranch.