diff options
Diffstat (limited to 'lib/dns/zone.c')
-rw-r--r-- | lib/dns/zone.c | 73 |
1 files changed, 51 insertions, 22 deletions
diff --git a/lib/dns/zone.c b/lib/dns/zone.c index d334bebc436cd..490248a689101 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2016 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -1052,6 +1052,8 @@ zone_free(dns_zone_t *zone) { isc_task_detach(&zone->task); if (zone->loadtask != NULL) isc_task_detach(&zone->loadtask); + if (zone->view != NULL) + dns_view_weakdetach(&zone->view); /* Unmanaged objects */ for (signing = ISC_LIST_HEAD(zone->signing); @@ -3408,7 +3410,8 @@ compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx, */ static void trust_key(dns_zone_t *zone, dns_name_t *keyname, - dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) { + dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) +{ isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned char data[4096]; @@ -8540,13 +8543,12 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { */ deletekey = ISC_TRUE; } else if (keydata.removehd == 0) { - /* Remove from secroots */ + /* + * Remove key from secroots. + */ dns_view_untrust(zone->view, keyname, &dnskey, mctx); - /* But ensure there's a null key */ - fail_secure(zone, keyname); - /* If initializing, delete now */ if (keydata.addhd == 0) deletekey = ISC_TRUE; @@ -8855,7 +8857,8 @@ zone_refreshkeys(dns_zone_t *zone) { result = dns_resolver_createfetch(zone->view->resolver, kname, dns_rdatatype_dnskey, NULL, NULL, NULL, - DNS_FETCHOPT_NOVALIDATE, + DNS_FETCHOPT_NOVALIDATE| + DNS_FETCHOPT_UNSHARED, zone->task, keyfetch_done, kfetch, &kfetch->dnskeyset, @@ -9303,6 +9306,7 @@ static void dump_done(void *arg, isc_result_t result) { const char me[] = "dump_done"; dns_zone_t *zone = arg; + dns_zone_t *secure = NULL; dns_db_t *db; dns_dbversion_t *version; isc_boolean_t again = ISC_FALSE; @@ -9316,30 +9320,54 @@ dump_done(void *arg, isc_result_t result) { if (result == ISC_R_SUCCESS && zone->journal != NULL && zone->journalsize != -1) { - /* * We don't own these, zone->dctx must stay valid. */ db = dns_dumpctx_db(zone->dctx); version = dns_dumpctx_version(zone->dctx); - tresult = dns_db_getsoaserial(db, version, &serial); + + /* + * Handle lock order inversion. + */ + again: + LOCK_ZONE(zone); + if (inline_raw(zone)) { + secure = zone->secure; + INSIST(secure != zone); + TRYLOCK_ZONE(result, secure); + if (result != ISC_R_SUCCESS) { + UNLOCK_ZONE(zone); + secure = NULL; +#if ISC_PLATFORM_USETHREADS + isc_thread_yield(); +#endif + goto again; + } + } + /* * If there is a secure version of this zone * use its serial if it is less than ours. */ - if (tresult == ISC_R_SUCCESS && inline_raw(zone) && - zone->secure->db != NULL) - { + if (tresult == ISC_R_SUCCESS && secure != NULL) { isc_uint32_t sserial; isc_result_t mresult; - mresult = dns_db_getsoaserial(zone->secure->db, - NULL, &sserial); - if (mresult == ISC_R_SUCCESS && - isc_serial_lt(sserial, serial)) - serial = sserial; + ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read); + if (secure->db != NULL) { + mresult = dns_db_getsoaserial(zone->secure->db, + NULL, &sserial); + if (mresult == ISC_R_SUCCESS && + isc_serial_lt(sserial, serial)) + serial = sserial; + } + ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read); } + if (secure != NULL) + UNLOCK_ZONE(secure); + UNLOCK_ZONE(zone); + /* * Note: we are task locked here so we can test * zone->xfr safely. @@ -10041,6 +10069,9 @@ notify_send(dns_notify_t *notify) { REQUIRE(DNS_NOTIFY_VALID(notify)); REQUIRE(LOCKED_ZONE(notify->zone)); + if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) + return; + for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL; ai = ISC_LIST_NEXT(ai, publink)) { @@ -10116,7 +10147,8 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime); UNLOCK_ZONE(zone); - if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || + ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) return; if (notifytype == dns_notifytype_no) @@ -11644,9 +11676,6 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) { zone->irefs--; } - if (zone->view != NULL) - dns_view_weakdetach(&zone->view); - /* * We have now canceled everything set the flag to allow exit_check() * to succeed. We must not unlock between setting this flag and @@ -17428,7 +17457,7 @@ dns_zone_keydone(dns_zone_t *zone, const char *keystr) { kd->all = ISC_TRUE; else { isc_textregion_t r; - char *algstr; + const char *algstr; dns_keytag_t keyid; dns_secalg_t alg; size_t n; |