]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Limit the number of addresses returned per ADB find
authorColin Vidal <colin@isc.org>
Thu, 5 Feb 2026 08:46:01 +0000 (09:46 +0100)
committerOndřej Surý <ondrej@isc.org>
Thu, 7 May 2026 13:14:06 +0000 (15:14 +0200)
Add a hard limit on the number of addresses that ADB returns from a
single NS lookup (dns_adbfind_t).  This mitigates a flood attack
where an attacker controls a zone with many addresses for a
nameserver, each returning an invalid response.  The global
max-query count (default 50) also limits this, but significant harm
can be done before that limit is reached.

The default limit is now 6 (v4 and/or v6) addresses for an ADB find (so,
ADB looking up for A/AAAA addresses of a name server name).

(cherry picked from commit 9b61b194c58c02d4fbbbe439eceeec8fd2a2a54c)

lib/dns/adb.c

index e12c804f2bb7c7f5ab53fce317046c4821f1b7f6..82126f975ea0581566b79e73c1b8746d38c570c3 100644 (file)
 
 #define DNS_ADB_MINADBSIZE      (1024U*1024U)     /*%< 1 Megabyte */
 
+/*
+ * Default for the per-find address limit, the sum of the number of A and AAAA
+ * RR from an ADB NS name resolution
+ */
+#define DEFAULT_ADDRSLIMIT 6
+
 typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
 typedef struct dns_adbnamehook dns_adbnamehook_t;
 typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
@@ -2183,6 +2189,7 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
        dns_adbaddrinfo_t *addrinfo;
        dns_adbentry_t *entry;
        int bucket;
+       size_t count = 0;
 
        bucket = DNS_ADB_INVALIDBUCKET;
 
@@ -2219,6 +2226,13 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
                        inc_entry_refcnt(adb, entry, false);
                        ISC_LIST_APPEND(find->list, addrinfo, publink);
                        addrinfo = NULL;
+
+                       if (++count >= DEFAULT_ADDRSLIMIT) {
+                               DP(ISC_LOG_DEBUG(3), "skipping addresses");
+                               UNLOCK(&adb->entrylocks[bucket]);
+                               return;
+                       }
+
                nextv4:
                        UNLOCK(&adb->entrylocks[bucket]);
                        bucket = DNS_ADB_INVALIDBUCKET;
@@ -2259,6 +2273,13 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
                        inc_entry_refcnt(adb, entry, false);
                        ISC_LIST_APPEND(find->list, addrinfo, publink);
                        addrinfo = NULL;
+
+                       if (++count >= DEFAULT_ADDRSLIMIT) {
+                               DP(ISC_LOG_DEBUG(3), "skipping addresses");
+                               UNLOCK(&adb->entrylocks[bucket]);
+                               return;
+                       }
+
                nextv6:
                        UNLOCK(&adb->entrylocks[bucket]);
                        bucket = DNS_ADB_INVALIDBUCKET;