]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix a race in RPZ with min-update-interval set to 0
authorWitold Kręcicki <wpk@isc.org>
Thu, 25 Oct 2018 18:49:28 +0000 (18:49 +0000)
committerWitold Kręcicki <wpk@isc.org>
Mon, 29 Oct 2018 22:04:00 +0000 (23:04 +0100)
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.

CHANGES
lib/dns/rpz.c

diff --git a/CHANGES b/CHANGES
index 323b684e6c4c2b2ad3d188a6f44f6c7baf1ad8b5..02e42282a4635dd685b5add80468d2ec98a4dc39 100644 (file)
--- 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]
 
index 1f919e1201536ae7c97c8178e65d376de3ec7a66..fa8b3d4491e3a0960146dbfabe5cad6d689d9277 100644 (file)
@@ -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);