From d6f2dd79f6f5817fda2ac44cb3a6a3da32a1e30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 5 Nov 2024 14:59:16 +0100 Subject: [PATCH] Revalidate the adbname when canceling the ADB find When canceling the ADB find, the lock on the find gets released for a brief period of time to be locked again inside adbname lock. During the brief period that the ADB find is unlocked, it can get canceled by other means removing it from the adbname list which in turn causes assertion failure due to a double removal from the adbname list. Recheck if the find->adbname is still valid after acquiring the lock again and if not just skip the double removal. Additionally, attach to the adbname as in the worst case, the adbname might also cease to exist if the scheduler would block this particular thread for a longer period of time invalidating the lock we are going to acquire and release. (cherry picked from commit 128e50e1ff888ff760f0753613edfe9bf360a857) --- lib/dns/adb.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/dns/adb.c b/lib/dns/adb.c index c7370a0820..be6b859649 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -2317,17 +2317,29 @@ dns_adb_cancelfind(dns_adbfind_t *find) { * locks in that order, to match locking hierarchy * elsewhere. */ + dns_adbname_ref(adbname); UNLOCK(&find->lock); + + /* + * Other thread could cancel the find between the unlock and + * lock, so we need to recheck whether the adbname is still + * valid and reference the adbname, so it does not vanish before + * we have a chance to lock it again. + */ + LOCK(&adbname->lock); LOCK(&find->lock); - ISC_LIST_UNLINK(adbname->finds, find, plink); - find->adbname = NULL; + if (find->adbname != NULL) { + ISC_LIST_UNLINK(find->adbname->finds, find, plink); + find->adbname = NULL; + } find_sendevent(find); UNLOCK(&find->lock); UNLOCK(&adbname->lock); + dns_adbname_detach(&adbname); } }