34afcc
From 26c4f3e1c9bcba6f61c44af4bfa7c585bfe43f0b Mon Sep 17 00:00:00 2001
34afcc
From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= <michal@isc.org>
34afcc
Date: Mon, 24 Sep 2018 19:33:16 +0200
34afcc
Subject: [PATCH] Prevent a race after zone load
34afcc
34afcc
Zone loading happens in a different task (zone->loadtask) than other
34afcc
zone actions (zone->task).  Thus, when zone_postload() is called in the
34afcc
context of zone->loadtask, it may cause zone maintenance to be queued in
34afcc
zone->task and another thread can then execute zone_maintenance() before
34afcc
zone_postload() gets a chance to finish its work in the first thread.
34afcc
This would not be a problem if zone_maintenance() accounted for this
34afcc
possibility by locking the zone before checking the state of its
34afcc
DNS_ZONEFLG_LOADPENDING flag.  However, the zone is currently not locked
34afcc
before the state of that flag is checked, which may prevent zone
34afcc
maintenance from happening despite zone_postload() scheduling it.  Fix
34afcc
by locking the zone in zone_maintenance() before checking the state of
34afcc
the zone's DNS_ZONEFLG_LOADPENDING flag.
34afcc
34afcc
(cherry picked from commit 56003e9f9f72c8be67d553f4dbd16eba849ca864)
34afcc
---
34afcc
 lib/dns/zone.c | 12 +++++-------
34afcc
 1 file changed, 5 insertions(+), 7 deletions(-)
34afcc
34afcc
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
34afcc
index 42a1811..f2ae6f3 100644
34afcc
--- a/lib/dns/zone.c
34afcc
+++ b/lib/dns/zone.c
34afcc
@@ -10005,12 +10005,6 @@ zone_maintenance(dns_zone_t *zone) {
34afcc
 	REQUIRE(DNS_ZONE_VALID(zone));
34afcc
 	ENTER;
34afcc
 
34afcc
-	/*
34afcc
-	 * Are we pending load/reload?
34afcc
-	 */
34afcc
-	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
34afcc
-		return;
34afcc
-
34afcc
 	/*
34afcc
 	 * Configuring the view of this zone may have
34afcc
 	 * failed, for example because the config file
34afcc
@@ -10019,7 +10013,11 @@ zone_maintenance(dns_zone_t *zone) {
34afcc
 	 * to do further maintenance on it.
34afcc
 	 */
34afcc
 	LOCK_ZONE(zone);
34afcc
-	viewok = (zone->view != NULL && zone->view->adb != NULL);
34afcc
+	/*
34afcc
+	 * Are we pending load/reload?
34afcc
+	 */
34afcc
+	viewok = (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
34afcc
+		  zone->view != NULL && zone->view->adb != NULL);
34afcc
 	UNLOCK_ZONE(zone);
34afcc
 	if (!viewok) {
34afcc
 		return;
34afcc
-- 
34afcc
2.31.1
34afcc