]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Use a keyed hash for the RRL bucket table
authorOndřej Surý <ondrej@isc.org>
Wed, 29 Apr 2026 16:20:03 +0000 (18:20 +0200)
committerOndřej Surý <ondrej@isc.org>
Mon, 4 May 2026 11:39:01 +0000 (13:39 +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
lib/dns/rrl.c

index 38405165e828d7534c048b0ebd90a9e7f7d96c13..91cf387f5ba744cdac1fbfe335881602a7d894a4 100644 (file)
@@ -22,6 +22,7 @@
 #include <inttypes.h>
 #include <stdbool.h>
 
+#include <isc/hash.h>
 #include <isc/log.h>
 #include <isc/mem.h>
 #include <isc/net.h>
@@ -372,14 +373,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);
 }
 
 /*