]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Assert adb find loop-affinity invariant at lifetime entry points 11943/head
authorOndřej Surý <ondrej@isc.org>
Fri, 1 May 2026 04:44:06 +0000 (06:44 +0200)
committerOndřej Surý <ondrej@isc.org>
Fri, 1 May 2026 05:50:29 +0000 (07:50 +0200)
The dns_adbfind_t lifetime model has no reference counting; storage
liveness is held together by find->lock and the FIND_EVENT_SENT
idempotency flag, plus an unwritten cross-module rule that all
non-trivial operations on a find run on find->loop. If a caller
violates that rule, the unlock-relock window in dns_adb_cancelfind
(and similar paths) becomes a use-after-free and we crash later
inside libpthread on a corrupted mutex.

Add REQUIREs at dns_adb_cancelfind, dns_adb_destroyfind and
find_sendevent so a violation aborts at the offending call site
rather than silently freeing storage another loop is still touching.
Also poison find->magic with ~DNS_ADBFIND_MAGIC in free_adbfind so
DNS_ADBFIND_VALID catches reuse-after-free at the next public entry
point instead of letting the dangling pointer reach the mutex code.

Assisted-by: Claude:claude-opus-4-7
lib/dns/adb.c

index 8e3a381f55f457967d7e5ff702714e0775d5c651..f189664f80c5d82c4d2df4769328437e506222ce 100644 (file)
@@ -1084,7 +1084,7 @@ free_adbfind(dns_adbfind_t **findp) {
        REQUIRE(!ISC_LINK_LINKED(find, plink));
        REQUIRE(find->adbname == NULL);
 
-       find->magic = 0;
+       find->magic = ~DNS_ADBFIND_MAGIC;
 
        isc_mutex_destroy(&find->lock);
 
@@ -2153,6 +2153,8 @@ dns_adb_destroyfind(dns_adbfind_t **findp) {
 
        DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
 
+       REQUIRE(find->loop == NULL || isc_loop() == find->loop);
+
        adb = find->adb;
 
        LOCK(&find->lock);
@@ -2178,6 +2180,8 @@ dns_adb_destroyfind(dns_adbfind_t **findp) {
  */
 static void
 find_sendevent(dns_adbfind_t *find) {
+       REQUIRE(find->loop != NULL && isc_loop() == find->loop);
+
        if (!FIND_EVENTSENT(find)) {
                atomic_store(&find->status, DNS_ADB_CANCELED);
 
@@ -2195,6 +2199,7 @@ dns_adb_cancelfind(dns_adbfind_t *find) {
 
        REQUIRE(DNS_ADBFIND_VALID(find));
        REQUIRE(DNS_ADB_VALID(find->adb));
+       REQUIRE(find->loop != NULL && isc_loop() == find->loop);
 
        LOCK(&find->lock);
        REQUIRE(FIND_WANTEVENT(find));