2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 14:07:59 +00:00

Merge branch '3288-adb-cancelfind-race' into 'main'

lock find when unlinking adbname->finds in dns_adb_cancelfind()

Closes #3288

See merge request isc-projects/bind9!6141
This commit is contained in:
Ondřej Surý
2022-04-26 11:34:44 +00:00

View File

@@ -2662,41 +2662,15 @@ dns_adb_destroyfind(dns_adbfind_t **findp) {
free_adbfind(&find);
}
void
dns_adb_cancelfind(dns_adbfind_t *find) {
isc_event_t *ev = NULL;
isc_task_t *task = NULL;
dns_adb_t *adb = NULL;
dns_adbname_t *adbname = NULL;
dns_adbnamebucket_t *nbucket = NULL;
LOCK(&find->lock);
DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
adb = find->adb;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(!FIND_EVENTFREED(find));
REQUIRE(FIND_WANTEVENT(find));
if (find->adbname == NULL) {
goto cleanup;
}
adbname = find->adbname;
find->adbname = NULL;
nbucket = adbname->bucket;
UNLOCK(&find->lock);
LOCK(&nbucket->lock);
ISC_LIST_UNLINK(adbname->finds, find, plink);
UNLOCK(&nbucket->lock);
LOCK(&find->lock);
cleanup:
/*
* Caller must hold find lock.
*/
static void
find_sendevent(dns_adbfind_t *find) {
if (!FIND_EVENTSENT(find)) {
ev = &find->event;
task = ev->ev_sender;
isc_event_t *ev = &find->event;
isc_task_t *task = ev->ev_sender;
ev->ev_sender = find;
ev->ev_type = DNS_EVENT_ADBCANCELED;
ev->ev_destroy = event_freefind;
@@ -2709,7 +2683,45 @@ cleanup:
isc_task_sendanddetach(&task, (isc_event_t **)&ev);
}
UNLOCK(&find->lock);
}
void
dns_adb_cancelfind(dns_adbfind_t *find) {
dns_adbname_t *adbname = NULL;
DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
REQUIRE(DNS_ADBFIND_VALID(find));
REQUIRE(DNS_ADB_VALID(find->adb));
LOCK(&find->lock);
REQUIRE(!FIND_EVENTFREED(find));
REQUIRE(FIND_WANTEVENT(find));
adbname = find->adbname;
if (adbname == NULL) {
find_sendevent(find);
UNLOCK(&find->lock);
} else {
/*
* Release the find lock, then acquire the bucket and find
* locks in that order, to match locking hierarchy
* elsewhere.
*/
UNLOCK(&find->lock);
LOCK(&adbname->bucket->lock);
LOCK(&find->lock);
if (find->adbname != NULL) {
ISC_LIST_UNLINK(adbname->finds, find, plink);
find->adbname = NULL;
}
find_sendevent(find);
UNLOCK(&find->lock);
UNLOCK(&adbname->bucket->lock);
}
}
void