]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix a use-after-free bug in dns_zonemgr_releasezone()
authorAram Sargsyan <aram@isc.org>
Thu, 5 Jan 2023 15:01:35 +0000 (15:01 +0000)
committerOndřej Surý <ondrej@isc.org>
Mon, 9 Jan 2023 14:14:31 +0000 (14:14 +0000)
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.

lib/dns/zone.c

index eab42bf8c0ecdf309f87fde1d00e247e274bb965..cd471738daba608bafa0c2b7d612de8843c64cfa 100644 (file)
@@ -18675,8 +18675,6 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
 
 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);
@@ -18691,19 +18689,13 @@ dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
                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