]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Preserve req->pos during reply validation to prevent packet truncation on retra...
authorVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 10 Nov 2025 09:21:36 +0000 (09:21 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 10 Nov 2025 09:21:36 +0000 (09:21 +0000)
The rdns_request_reply_cmp function modifies req->pos as a side effect
during reply validation. This caused packet truncation on retransmits
because req->pos (which tracks the full packet length) was overwritten
with the end position of the question section.

On timeout/retry, rdns_send_request would use the corrupted req->pos
value, resulting in truncated packets missing the OPT additional section.
This made resolvers like Knot and PowerDNS unable to parse retransmitted
packets.

Fix by saving and restoring req->pos around the reply comparison logic.

contrib/librdns/resolver.c

index 117c85e15d379a585800374b40fe296ae878e922..0613a6b4e5cb49591d62c68679c4d81522c6b077 100644 (file)
@@ -220,17 +220,20 @@ rdns_parse_reply(uint8_t *in, int r, struct rdns_request *req,
         * Now we have request and query data is now at the end of header, so compare
         * request QR section and reply QR section
         */
+       unsigned int saved_pos = req->pos;
        req->pos = sizeof(struct dns_header);
        pos = in + sizeof(struct dns_header);
        t = r - sizeof(struct dns_header);
        for (i = 0; i < (int) qdcount; i++) {
                if ((npos = rdns_request_reply_cmp(req, pos, t)) == NULL) {
                        rdns_info("DNS request with id %d is for different query, ignoring", (int) req->id);
+                       req->pos = saved_pos;
                        return false;
                }
                t -= npos - pos;
                pos = npos;
        }
+       req->pos = saved_pos;
        /*
         * Now pos is in answer section, so we should extract data and form reply
         */