From: Vsevolod Stakhov Date: Wed, 20 May 2026 11:05:08 +0000 (+0100) Subject: [Fix] rdns: reject DNS labels that overrun the packet X-Git-Tag: 4.1.0~45 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c2fd2e002fce1fa846bc9278da1616459b9a5092;p=thirdparty%2Frspamd.git [Fix] rdns: reject DNS labels that overrun the packet rdns_parse_labels computes the name length in a first pass that only reads label length bytes, then a second pass copies the label data. The first pass never checked that a label's data actually fits within the packet, so a reply whose final label declared more bytes than remained made the second-pass memcpy read past the end of the reply buffer. On the DNS-over-TCP path that buffer is malloc'd to exactly the advertised message size, so the over-read ran past the allocation. Validate in the first pass that both plain and compressed label data stay within the packet, and reject the name otherwise. Also fix an off-by-one in rdns_decompress_label where an offset equal to the packet length was accepted and read one byte past the end. --- diff --git a/contrib/librdns/parse.c b/contrib/librdns/parse.c index f9025e1597..17afd8e895 100644 --- a/contrib/librdns/parse.c +++ b/contrib/librdns/parse.c @@ -31,7 +31,7 @@ rdns_decompress_label (uint8_t *begin, uint16_t *len, uint16_t max) { uint16_t offset = (*len); - if (offset > max) { + if (offset >= max) { return NULL; } *len = *(begin + offset); @@ -169,6 +169,10 @@ rdns_parse_labels (struct rdns_resolver *resolver, rdns_info ("invalid pointer in DNS packet"); return false; } + if (l + *l + 1 > end) { + rdns_info("invalid DNS label: compressed data overruns the packet"); + return false; + } begin = l; length = end - begin; p = l + *l + 1; @@ -182,6 +186,10 @@ rdns_parse_labels (struct rdns_resolver *resolver, } } else { + if (p + llen + 1 > end) { + rdns_info("invalid DNS label: data overruns the packet"); + return false; + } namelen += llen; p += llen + 1; labels ++;