]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Prevent a race after zone load
authorMichał Kępień <michal@isc.org>
Mon, 24 Sep 2018 17:33:16 +0000 (19:33 +0200)
committerEvan Hunt <each@isc.org>
Thu, 27 Sep 2018 02:46:09 +0000 (19:46 -0700)
Zone loading happens in a different task (zone->loadtask) than other
zone actions (zone->task).  Thus, when zone_postload() is called in the
context of zone->loadtask, it may cause zone maintenance to be queued in
zone->task and another thread can then execute zone_maintenance() before
zone_postload() gets a chance to finish its work in the first thread.
This would not be a problem if zone_maintenance() accounted for this
possibility by locking the zone before checking the state of its
DNS_ZONEFLG_LOADPENDING flag.  However, the zone is currently not locked
before the state of that flag is checked, which may prevent zone
maintenance from happening despite zone_postload() scheduling it.  Fix
by locking the zone in zone_maintenance() before checking the state of
the zone's DNS_ZONEFLG_LOADPENDING flag.

(cherry picked from commit 56003e9f9f72c8be67d553f4dbd16eba849ca864)

lib/dns/zone.c

index 19f3ddac66a991ed4fff1c7ba27da2dec00ff755..b9de7f33ec993576a9f87e948f4b44503faa4b5d 100644 (file)
@@ -10054,7 +10054,7 @@ zone_maintenance(dns_zone_t *zone) {
        const char me[] = "zone_maintenance";
        isc_time_t now;
        isc_result_t result;
-       bool dumping;
+       bool dumping, load_pending;
 
        REQUIRE(DNS_ZONE_VALID(zone));
        ENTER;
@@ -10062,8 +10062,13 @@ zone_maintenance(dns_zone_t *zone) {
        /*
         * Are we pending load/reload?
         */
-       if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
+       LOCK_ZONE(zone);
+       load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
+       UNLOCK_ZONE(zone);
+
+       if (load_pending) {
                return;
+       }
 
        /*
         * Configuring the view of this zone may have