]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: resolvers: skip the data of ignored additional records
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 29 Sep 2026 07:19:03 +0000 (09:19 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 10 Nov 2026 14:47:52 +0000 (15:47 +0100)
When parsing the additional records of an SRV response, records which are
not A or AAAA, or whose family is not accepted by dns-accept-family, are
ignored, but resolv_validate_dns_response() then moves on to the next
record without skipping the ignored record's data. The next record's
name is thus read from the middle of the ignored one's data, which
usually fails and makes all remaining additional records be ignored as
well (resolv_read_name() fails or returns an empty name, and the loop
continues at the same place), or may even produce bogus records if the
data happens to look like a valid record.

The glue records carrying the SRV targets' addresses are then lost, and
the servers' addresses have to be resolved with extra A/AAAA queries.
Since commit c84c15d39 ("BUG/MINOR: resolvers: Apply dns-accept-family
setting on additional records") this also concerns AAAA records when
IPv6 is not accepted, which is the default on hosts without IPv6
connectivity (dns-accept-family defaults to "auto"), so any SRV response
with AAAA glue records placed before the A ones is affected there.

This can be reproduced with "dns-accept-family ipv4" and an SRV response
whose additional section contains an AAAA record for the first target
followed by A records for all targets: the A records are never used and
A queries are sent for all targets.

Let's skip the record's data when ignoring it.

The problem has existed for unknown record types since the additional
records parsing was introduced. This must be backported to all stable
branches.

src/resolvers.c

index 776b8a999fc65b77e1c28c20c57e3a58a6fba3d4..910267bbcf429ad889fa8ea238ec9ed043ae39a0 100644 (file)
@@ -1573,6 +1573,8 @@ static int resolv_validate_dns_response(unsigned char *resp, unsigned char *bufe
                        memcpy(&answer_record->data.in6.sin6_addr, reader, answer_record->data_len);
                }
                else {
+                       /* ignored record, skip its data */
+                       reader += answer_record->data_len;
                        pool_free(resolv_answer_item_pool, answer_record);
                        answer_record = NULL;
                        continue;