dns_packet_append_name() added every name it appends to the packet's compression map, including names written at offsets >= 0x4000 that an RFC 1035 compression pointer (14 bits) can never reference. Such entries are not just useless -- when the same name occurs again, the lookup finds it, the pointer cannot be emitted, the code falls through to appending the labels again, and the re-insertion into the map then fails the whole packet build with hashmap_ensure_put() returning -EEXIST. This is easily triggered with mDNS: an unsolicited DNS-SD announcement covering a zone with a few hundred services exceeds 16KiB, and dns_scope_announce() then fails with "Failed to build reply packet: File exists". This lifts the failure only: dns_scope_announce() still builds the whole zone into one packet and hands it to the socket as a single datagram, fragmented as the link requires. Splitting announcements across MTU-sized packets, as RFC 6762 section 17 asks, is done separately. Only insert a name into the map if its offset is pointer-expressible, making "mapped implies referenceable" a map invariant. Re-occurrences of out-of-range names are emitted as labels again -- the only encoding RFC 1035 section 4.1.4 permits in that case -- still compressed from the first suffix that is mapped in range. The lookup restates that range as control flow rather than asserting it. Under -Db_ndebug=true, which CI builds, assert() is __builtin_unreachable(), so an out-of-range entry would put 0xC000 | n truncated to 14 bits on the wire -- a pointer to an arbitrary earlier offset -- where falling through emits the labels instead. This layer is shared with unicast DNS, DoT and LLMNR. The pointer's tag bits and its offset bound are now named once, in dns-def.h next to the other wire-format constants rather than in dns-packet.h, since the format is RFC 1035's and not this packet abstraction's -- dhcp-message.c open-codes the same two bits to parse compressed names out of DHCP options. Compile-time checks pin that the two partition the 16-bit field and that the tag is its top two bits, which is what lets the reader take it from the first octet alone. The offset's other bound becomes control flow along with it: it was an assert(), which under -Db_ndebug=true is no check at all, for the bound whose violation puts a pointer to the wrong bytes on the wire. It is also tightened to the start of the name being appended rather than the end of the packet, which is the "prior occurrence" RFC 1035 section 4.1.4 allows a pointer to address and what dns_packet_read_name() enforces on the way in. Add regression tests, including one through dns_packet_append_rr() -- the path the reported failure came from, where the name append is nested inside the rdlength backpatch and two further rollbacks -- and one for the reader's label-type dispatch, which the renamed constants touch.
System and Service Manager
Details
Most documentation is available on systemd's website.
Assorted, older, general information about systemd can be found in the systemd Wiki.
Information about build requirements is provided in the README file.
Consult our NEWS file for information about what's new in the most recent systemd versions.
Please see the Code Map for information about this repository's layout and content.
Please see the Hacking guide for information on how to hack on systemd and test your modifications.
Please see our Contribution Guidelines for more information about filing GitHub Issues and posting GitHub Pull Requests.
When preparing patches for systemd, please follow our Coding Style Guidelines.
If you are looking for support, please contact our mailing list, join our IRC channel #systemd on libera.chat or Matrix channel
Stable branches with backported patches are available in the stable repo.
We have a security bug bounty program sponsored by the Sovereign Tech Fund hosted on YesWeHack
Repositories with distribution packages built from git main are available on OBS, and also repositories with packages built from the latest stable release
