]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix reference counting in do_nsfetch()
authorMichał Kępień <michal@isc.org>
Mon, 18 Dec 2023 10:33:43 +0000 (11:33 +0100)
committerMichał Kępień <michal@isc.org>
Mon, 18 Dec 2023 10:33:43 +0000 (11:33 +0100)
Each function queuing a do_nsfetch() call using isc_async_run() is
expected to increase the given zone's internal reference count
(zone->irefs), which is then correspondingly decreased in either
do_nsfetch() itself (when the dns_resolver_createfetch() fails) or in
nsfetch_done() (when recursion is finished).

However, do_nsfetch() can also return early if either the zone itself or
the relevant view's resolver object is being shut down.  In that case,
do_nsfetch() simply returns without decreasing the internal reference
count for the zone.  This leaves a dangling zone reference around, which
leads to hangs during named shutdown.

Fix by executing the same cleanup code for early returns from
do_nsfetch() as for a failed dns_resolver_createfetch() call in that
function as the reference count will not be decreased in nsfetch_done()
in any of these cases.

lib/dns/zone.c

index 9f54bc6ddb60caf295ff6db7849d95b406ad13a8..28e6226462865197f3450ff8b28c2523dda58282 100644 (file)
@@ -21049,12 +21049,13 @@ do_nsfetch(void *arg) {
        unsigned int options = DNS_FETCHOPT_UNSHARED | DNS_FETCHOPT_NOCACHED;
 
        if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
-               return;
+               result = ISC_R_SHUTTINGDOWN;
+               goto cleanup;
        }
 
        result = dns_view_getresolver(zone->view, &resolver);
        if (result != ISC_R_SUCCESS) {
-               return;
+               goto cleanup;
        }
 
        if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
@@ -21085,6 +21086,7 @@ do_nsfetch(void *arg) {
 
        dns_resolver_detach(&resolver);
 
+cleanup:
        if (result != ISC_R_SUCCESS) {
                dns_name_t *zname = dns_fixedname_name(&nsfetch->name);
                bool free_needed;