The dns_zonemgr_releasezone() function makes a decision to destroy
'zmgr' (based on its references count, after decreasing it) inside
a lock, and then destroys the object outside of the lock.
This causes a race with dns_zonemgr_detach(), which could destroy
the object in the meantime.
Change dns_zonemgr_releasezone() to detach from 'zmgr' and destroy
the object (if needed) using dns_zonemgr_detach(), outside of the
lock.
(cherry picked from commit
c1fc2122531bdd27ca38434a2632e8dac532bc13)
void
dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
- bool free_now = false;
-
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
REQUIRE(zone->zmgr == zmgr);
ENSURE(zone->kfio == NULL);
}
+ /* Detach below, outside of the write lock. */
zone->zmgr = NULL;
- if (isc_refcount_decrement(&zmgr->refs) == 1) {
- free_now = true;
- }
-
UNLOCK_ZONE(zone);
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
- if (free_now) {
- zonemgr_free(zmgr);
- }
- ENSURE(zone->zmgr == NULL);
+ dns_zonemgr_detach(&zmgr);
}
void