From e2e6fd4fa09494c703774c3adb838bfca79b899b Mon Sep 17 00:00:00 2001
From: Diego Fronza <diego@isc.org>
Date: Wed, 7 Apr 2021 10:48:12 -0300
Subject: [PATCH] Resolve TSAN data race in zone_maintenance

Fix race between zone_maintenance and dns_zone_notifyreceive functions,
zone_maintenance was attempting to read a zone flag calling
DNS_ZONE_FLAG(zone, flag) while dns_zone_notifyreceive was updating
a flag in the same zone calling DNS_ZONE_SETFLAG(zone, ...).

The code reading the flag in zone_maintenance was not protected by the
zone's lock, to avoid a race the zone's lock is now being acquired
before an attempt to read the zone flag is made.
Conflict: delete start_refresh
Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/e2e6fd4fa09494c703774c3adb838bfca79b899b
---
 lib/dns/zone.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index a895b25434..9866f85184 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -10187,6 +10187,7 @@ zone_maintenance(dns_zone_t *zone) {
 	isc_time_t now;
 	isc_result_t result;
 	bool dumping, load_pending, viewok;
+	bool need_notify;
 
 	REQUIRE(DNS_ZONE_VALID(zone));
 	ENTER;
@@ -10268,11 +10269,16 @@ zone_maintenance(dns_zone_t *zone) {
 	/*
 	 * Slaves send notifies before backing up to disk, masters after.
 	 */
-	if (zone->type == dns_zone_slave &&
-	    (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
-	     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
-	    isc_time_compare(&now, &zone->notifytime) >= 0)
+	LOCK_ZONE(zone);
+	need_notify = zone->type == dns_zone_slave &&
+		      (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
+		       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
+		      (isc_time_compare(&now, &zone->notifytime) >= 0);
+	UNLOCK_ZONE(zone);
+
+	if (need_notify) {
 		zone_notify(zone, &now);
+	}
 
 	/*
 	 * Do we need to consolidate the backing store?
-- 
2.23.0

