summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-11-10 14:48:13 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-02-17 18:36:44 +0100
commitc8b7432cba73a4215538726cd98da23a8de9b426 (patch)
tree1f50582dbe8a9d5f119a4dcc2dd9737d51b0d8a3
parent21816aec6ade814e458040d45878ec9b69d220fc (diff)
downloadsystemd-c8b7432cba73a4215538726cd98da23a8de9b426.tar.gz
resolved: gracefully handle with packets with too large RR count
Apparently, there are plenty routers in place that report an incorrect RR count in the packets: they declare more RRs than are actually included. Let's accept these responses, but let's downgrade them to baseline, i.e. let's suppress OPT in this case: if they don't even get the RR count right, let's operate on the absolute baseline, and not bother with anything fancier such as EDNS. Prompted-by: https://github.com/systemd/systemd/issues/12841#issuecomment-724063973 Fixes: #3980 Most likely fixes: #12841 (cherry picked from commit 18674159ebbf622a9e6e5a45cc36b38f74dae315) (cherry picked from commit fdfffdaf20a18a50c9a6d858359cf4af6d2f4c8b)
-rw-r--r--src/resolve/resolved-dns-packet.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index 90a40244b1..e97d9c6a12 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -2210,6 +2210,18 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
if (r < 0)
return r;
+ if (p->rindex == p->size) {
+ /* If we reached the end of the packet already, but there are still more RRs
+ * declared, then that's a corrupt packet. Let's accept the packet anyway, since it's
+ * apparently a common bug in routers. Let's however suppress OPT support in this
+ * case, so that we force the rest of the logic into lowest DNS baseline support. Or
+ * to say this differently: if the DNS server doesn't even get the RR counts right,
+ * it's highly unlikely it gets EDNS right. */
+ log_debug("More resource records declared in packet than included, suppressing OPT.");
+ bad_opt = true;
+ break;
+ }
+
/* Try to reduce memory usage a bit */
if (previous)
dns_resource_key_reduce(&rr->key, &previous->key);
@@ -2295,8 +2307,10 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
previous = dns_resource_record_ref(rr);
}
- if (bad_opt)
+ if (bad_opt) {
p->opt = dns_resource_record_unref(p->opt);
+ p->opt_start = p->opt_size = SIZE_MAX;
+ }
*ret_answer = TAKE_PTR(answer);