From: Witold Kręcicki Date: Thu, 25 Oct 2018 18:49:28 +0000 (+0000) Subject: Fix a race in RPZ with min-update-interval set to 0 X-Git-Tag: v9.13.4~74^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=faf2c7711aadde2c9bf7a142e7a53fc26236ebae;p=thirdparty%2Fbind9.git Fix a race in RPZ with min-update-interval set to 0 If another RPZ update is pending when processing the previous one nears completion and min-update-interval is set to 0, isc_timer_reset() gets called with 'interval' set to 0, which triggers an assertion failure. To prevent such a scenario from causing a crash, queue the update event directly instead of asking the timer thread to do it. --- diff --git a/CHANGES b/CHANGES index 323b684e6c4..02e42282a46 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +5069. [bug] Fix a hang on in RPZ when named is shutdown during RPZ + zone update. [GL !907] + +5068. [bug] Fix a race in RPZ with min-update-interval set to 0. + [GL #643] + 5067. [bug] Don't minimize qname when sending the query to a forwarder. [GL #361] diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index 1f919e12015..fa8b3d4491e 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1802,18 +1802,30 @@ finish_update(dns_rpz_zone_t *rpz) { * If there's an update pending schedule it */ if (rpz->updatepending == true) { - uint64_t defer = rpz->min_update_interval; - isc_interval_t interval; - dns_name_format(&rpz->origin, dname, - DNS_NAME_FORMATSIZE); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_MASTER, ISC_LOG_INFO, - "rpz: %s: new zone version came " - "too soon, deferring update for " - "%" PRIu64 " seconds", dname, defer); - isc_interval_set(&interval, (unsigned int)defer, 0); - isc_timer_reset(rpz->updatetimer, isc_timertype_once, - NULL, &interval, true); + if (rpz->min_update_interval > 0) { + uint64_t defer = rpz->min_update_interval; + isc_interval_t interval; + dns_name_format(&rpz->origin, dname, + DNS_NAME_FORMATSIZE); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_MASTER, ISC_LOG_INFO, + "rpz: %s: new zone version came " + "too soon, deferring update for " + "%" PRIu64 " seconds", dname, defer); + isc_interval_set(&interval, (unsigned int)defer, 0); + isc_timer_reset(rpz->updatetimer, isc_timertype_once, + NULL, &interval, true); + } else { + isc_event_t *event; + INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link)); + ISC_EVENT_INIT(&rpz->updateevent, + sizeof(rpz->updateevent), 0, NULL, + DNS_EVENT_RPZUPDATED, + dns_rpz_update_taskaction, + rpz, rpz, NULL, NULL); + event = &rpz->updateevent; + isc_task_send(rpz->rpzs->updater, &event); + } } UNLOCK(&rpz->rpzs->maint_lock);