]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Use a keyed hash for the RRL bucket table 11952/head
authorOndřej Surý <ondrej@isc.org>
Wed, 29 Apr 2026 16:20:03 +0000 (18:20 +0200)
committerOndřej Surý <ondrej@sury.org>
Mon, 4 May 2026 14:15:58 +0000 (16:15 +0200)
The previous hash_key() was a deterministic, unkeyed (<<1) + add over the
key words.  An off-path attacker could invert it offline and submit
queries whose source /24, qname hash, and qtype map to a single bucket;
under chaining this turns every lookup into an O(N) walk under
rrl->lock and starves legitimate query processing on the very feature
deployed to mitigate DoS.

Replace it with isc_hash32(), which is HalfSipHash-2-4 keyed by a
per-process random seed, so collision sets cannot be precomputed.

Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit a6b7ce29c4cfab2ab1d46f48f21f531d5ffde942)

lib/dns/rrl.c

index 4a6de0144a6c61ef545b66e962ab809e6abe56c3..7ff79f87c7db8783d341de6680af11d8a4b3fe69 100644 (file)
@@ -22,6 +22,8 @@
 #include <inttypes.h>
 #include <stdbool.h>
 
+#include <isc/hash.h>
+#include <isc/log.h>
 #include <isc/mem.h>
 #include <isc/net.h>
 #include <isc/netaddr.h>
@@ -374,14 +376,12 @@ key_cmp(const dns_rrl_key_t *a, const dns_rrl_key_t *b) {
 
 static uint32_t
 hash_key(const dns_rrl_key_t *key) {
-       uint32_t hval;
-       int i;
-
-       hval = key->w[0];
-       for (i = sizeof(key->w) / sizeof(key->w[0]) - 1; i >= 0; --i) {
-               hval = key->w[i] + (hval << 1);
-       }
-       return hval;
+       /*
+        * The key includes attacker-controlled bits (client /24, qname
+        * hash, qtype). Use the keyed, per-process-randomised hash so
+        * collisions cannot be engineered to overload one bucket chain.
+        */
+       return isc_hash32(key, sizeof(*key), true);
 }
 
 /*