From 272afcd999cb07593f5dd943e22dc1a03d42b090 Mon Sep 17 00:00:00 2001
From: Aram Sargsyan <aram@isc.org>
Date: Thu, 5 Jan 2023 15:01:35 +0000
Subject: [PATCH] Fix a use-after-free bug in dns_zonemgr_releasezone()

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.

Conflict: NA
Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/272afcd999cb07593f5dd943e22dc1a03d42b090

(cherry picked from commit c1fc2122531bdd27ca38434a2632e8dac532bc13)
---
 lib/dns/zone.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 4b864da..bf47aa0 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -18815,8 +18815,6 @@ unlock:
 
 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);
@@ -18828,19 +18826,13 @@ dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
 
 	zonemgr_keymgmt_delete(zmgr, zone);
 
+	/* 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
-- 
2.33.0

