dns-packet: limit the number of jumps during packet decompression

So far we didn't limit the number of jumps when decompressing a DNS
packet. This can lead to some extra work with specially crafted packets
that send a staircase of thousands of descending compression pointers,
which can then be amplified by referencing such staircase from thousands
of names.

Given that legitimate DNS packets need only a handful of jumps in the
compression chains, let's limit the number of jumps per a single name to
256 (the same limit as, for example, Unbound currently has).

Reported by opensec-intelligence (OpenSec).
This commit is contained in:
Frantisek Sumsal
2026-09-22 15:55:13 +02:00
committed by Luca Boccassi
parent 726cc309b4
commit efa16c7f31
3 changed files with 120 additions and 1 deletions
+4 -1
View File
@@ -1583,7 +1583,7 @@ int dns_packet_read_name(
assert(p);
_cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
size_t after_rindex = 0, jump_barrier = p->rindex;
size_t after_rindex = 0, jump_barrier = p->rindex, jumps = 0;
_cleanup_free_ char *name = NULL;
bool first = true;
size_t n = 0, m = 0;
@@ -1643,6 +1643,9 @@ int dns_packet_read_name(
if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier)
return -EBADMSG;
if (jumps++ >= DNS_COMPRESSION_JUMPS_MAX)
return -EBADMSG;
if (after_rindex == 0)
after_rindex = p->rindex;
+3
View File
@@ -51,6 +51,9 @@ assert_cc(sizeof(DnsPacketHeader) == 12);
/* With EDNS0 we can use larger packets, default to 1232, which is what is commonly used */
#define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 1232u
/* Maximum number of compression pointers we are willing to follow while decoding a single name */
#define DNS_COMPRESSION_JUMPS_MAX 256U
typedef struct DnsPacket {
unsigned n_ref;
DnsProtocol protocol;