From a490c091217d3d83e090d0f0399cb5f14baf91bb Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 7 Feb 2019 15:25:28 +0100 Subject: [PATCH] named crashes on shutdown after load rpz failed This may happen when loading an RPZ failed and the code path skips calling dns_db_endload(). The dns_rpz_zone_t object is still kept marked as having registered db. So when this object is finally destroyed in rpz_detach(), this code will incorrectly call `dns_db_updatenotify_unregister()`: if (rpz->db_registered) dns_db_updatenotify_unregister(rpz->db, dns_rpz_dbupdate_callback, rpz); and trigger this assertion failure: REQUIRE(db != NULL); To fix this, only call `dns_db_updatenotify_unregister()` when `rpz->db` is not NULL. --- lib/dns/rpz.c | 9 ++++----- lib/dns/zone.c | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index e3b2f25698..d7112b01ed 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1586,7 +1586,6 @@ dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) { LOCK(&zone->rpzs->maint_lock); REQUIRE(zone->db_registered); - /* New zone came as AXFR */ if (zone->db != NULL && zone->db != db) { /* We need to clean up the old DB */ @@ -2097,14 +2096,14 @@ rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) { if (dns_name_dynamic(&rpz->cname)) { dns_name_free(&rpz->cname, rpzs->mctx); } - if (rpz->db_registered) { - dns_db_updatenotify_unregister(rpz->db, - dns_rpz_dbupdate_callback, rpz); - } if (rpz->dbversion != NULL) { dns_db_closeversion(rpz->db, &rpz->dbversion, false); } if (rpz->db != NULL) { + if (rpz->db_registered) { + dns_db_updatenotify_unregister( + rpz->db, dns_rpz_dbupdate_callback, rpz); + } dns_db_detach(&rpz->db); } if (rpz->updaterunning) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index f2087658c8..5e6988cfdf 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -2120,7 +2120,7 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) { } } - if (! dns_db_ispersistent(db)) { + if (!dns_db_ispersistent(db)) { if (zone->masterfile != NULL) { result = zone_startload(db, zone, loadtime); } else {