From: Ondřej Surý Date: Fri, 1 May 2026 04:44:06 +0000 (+0200) Subject: Assert adb find loop-affinity invariant at lifetime entry points X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d468cb21ff87d99d5e13e92fe7578e5b5783bd2;p=thirdparty%2Fbind9.git Assert adb find loop-affinity invariant at lifetime entry points 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 --- diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 8e3a381f55f..f189664f80c 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -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));