mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-23 10:37:43 -04:00
Fix cache flush ordering on NTA expiry
dns_view_flushnode() was called in the delete_expired() async callback, which runs after the query that detected the NTA expiry. This created a race: the query would proceed with stale cached data from the NTA period before the flush had a chance to run, resulting in transient SERVFAIL with EDE 22 (No Reachable Authority). Move dns_view_flushnode() into dns_ntatable_covered() so the cache is flushed synchronously when the expiry is detected, before the query continues. Also simplify the expiry comparison in delete_expired() to a direct pointer comparison (nta == pval) instead of comparing expiry timestamps.
This commit is contained in:
parent
892f50712d
commit
da8e1c956a
1 changed files with 11 additions and 13 deletions
|
|
@ -373,7 +373,6 @@ delete_expired(void *arg) {
|
|||
isc_result_t result;
|
||||
dns_qp_t *qp = NULL;
|
||||
void *pval = NULL;
|
||||
bool flushnode = false;
|
||||
|
||||
REQUIRE(VALID_NTATABLE(ntatable));
|
||||
|
||||
|
|
@ -387,17 +386,12 @@ delete_expired(void *arg) {
|
|||
dns_qpmulti_write(table, &qp);
|
||||
result = dns_qp_getname(qp, &nta->name, DNS_DBNAMESPACE_NORMAL, &pval,
|
||||
NULL);
|
||||
if (result == ISC_R_SUCCESS &&
|
||||
CMM_LOAD_SHARED(((dns__nta_t *)pval)->expiry) ==
|
||||
CMM_LOAD_SHARED(nta->expiry))
|
||||
{
|
||||
if (result == ISC_R_SUCCESS && nta == pval) {
|
||||
char nb[DNS_NAME_FORMATSIZE];
|
||||
dns_name_format(&nta->name, nb, sizeof(nb));
|
||||
isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_NTA,
|
||||
ISC_LOG_INFO, "deleting expired NTA at %s", nb);
|
||||
|
||||
flushnode = true;
|
||||
|
||||
result = dns_qp_deletename(qp, &nta->name,
|
||||
DNS_DBNAMESPACE_NORMAL, NULL, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
|
@ -406,9 +400,6 @@ delete_expired(void *arg) {
|
|||
}
|
||||
dns_qp_compact(qp, DNS_QPGC_MAYBE);
|
||||
dns_qpmulti_commit(table, &qp);
|
||||
if (flushnode) {
|
||||
dns_view_flushnode(view, &nta->name, true);
|
||||
}
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
dns__nta_detach(&nta);
|
||||
|
|
@ -423,15 +414,16 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
|
|||
bool answer = false;
|
||||
dns_qpread_t qpr;
|
||||
void *pval = NULL;
|
||||
bool flushnode = false;
|
||||
|
||||
REQUIRE(VALID_NTATABLE(ntatable));
|
||||
REQUIRE(dns_name_isabsolute(name));
|
||||
|
||||
rcu_read_lock();
|
||||
dns_view_t *view = rcu_dereference(ntatable->view);
|
||||
dns_qpmulti_t *table = rcu_dereference(ntatable->table);
|
||||
if (table == NULL) {
|
||||
rcu_read_unlock();
|
||||
return false;
|
||||
if (view == NULL || table == NULL) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
dns_qpmulti_query(table, &qpr);
|
||||
|
|
@ -462,6 +454,7 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
|
|||
/* NTA is expired */
|
||||
dns__nta_ref(nta);
|
||||
dns_ntatable_ref(nta->ntatable);
|
||||
flushnode = true;
|
||||
isc_async_run(nta->loop, delete_expired, nta);
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -469,6 +462,11 @@ dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
|
|||
answer = true;
|
||||
done:
|
||||
dns_qpread_destroy(table, &qpr);
|
||||
|
||||
if (nta != NULL && flushnode) {
|
||||
dns_view_flushnode(view, &nta->name, true);
|
||||
}
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
return answer;
|
||||
|
|
|
|||
Loading…
Reference in a new issue