]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Lock zone before checking whether its asynchronous load is already pending
authorMichał Kępień <michal@isc.org>
Thu, 15 Feb 2018 19:31:49 +0000 (20:31 +0100)
committerMichał Kępień <michal@isc.org>
Fri, 16 Feb 2018 07:59:46 +0000 (08:59 +0100)
While this is not an issue in named, which only calls
dns_zone_asyncload() from task-exclusive mode, this function is exported
by libdns and thus may in theory be concurrently called for the same
zone by multiple threads.  It also does not hurt to be consistent
locking-wise with other DNS_ZONEFLG_LOADPENDING accesses.

lib/dns/zone.c

index 3566e8764d2adbe2b4afc4821f3b2f051d796fb5..603aec91bae295e09f6922d8dcb41bf6e5f8ba68 100644 (file)
@@ -2127,8 +2127,11 @@ dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
                return (ISC_R_FAILURE);
 
        /* If we already have a load pending, stop now */
-       if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
+       LOCK_ZONE(zone);
+       if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
+               UNLOCK_ZONE(zone);
                return (ISC_R_ALREADYRUNNING);
+       }
 
        asl = isc_mem_get(zone->mctx, sizeof (*asl));
        if (asl == NULL)
@@ -2145,7 +2148,6 @@ dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
        if (e == NULL)
                CHECK(ISC_R_NOMEMORY);
 
-       LOCK_ZONE(zone);
        zone_iattach(zone, &asl->zone);
        DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
        isc_task_send(zone->loadtask, &e);
@@ -2156,6 +2158,7 @@ dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
   failure:
        if (asl != NULL)
                isc_mem_put(zone->mctx, asl, sizeof (*asl));
+       UNLOCK_ZONE(zone);
        return (result);
 }