From: Michał Kępień Date: Thu, 15 Feb 2018 19:31:49 +0000 (+0100) Subject: Lock zone before checking whether its asynchronous load is already pending X-Git-Tag: v9.12.1rc1~4^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93c176d2d6bcdb37ec5f02370ae2fa1e7b2e96b7;p=thirdparty%2Fbind9.git Lock zone before checking whether its asynchronous load is already pending 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. --- diff --git a/lib/dns/zone.c b/lib/dns/zone.c index ed9ae40c7c1..99a03afd048 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -2217,8 +2217,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) @@ -2235,7 +2238,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); @@ -2246,6 +2248,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); }