[CVE-2025-40777] sec: usr: Fix a possible assertion failure when using the 'stale-answer-client-timeout 0' option

In specific circumstances the :iscman:`named` resolver process could
terminate unexpectedly when stale answers were enabled and the
``stale-answer-client-timeout 0`` configuration option was used.
This has been fixed.

See isc-projects/bind9#5372

Merge branch '5372-security-serve-stale-crash-on-insist-unreachable' into 'v9.21.10-release'

See merge request isc-private/bind9!808
This commit is contained in:
Andoni Duarte 2025-07-03 10:52:28 +00:00
commit 7fafa0e48f

View file

@ -5635,16 +5635,14 @@ ns__query_start(query_ctx_t *qctx) {
}
}
if (!qctx->is_zone && qctx->view->staleanswerclienttimeout == 0 &&
dns_view_staleanswerenabled(qctx->view))
{
/*
* If stale answers are enabled and
* stale-answer-client-timeout is zero, then we can promptly
* answer with a stale RRset if one is available in cache.
*/
qctx->options.stalefirst = true;
}
/*
* If stale answers are enabled and stale-answer-client-timeout is zero,
* then we can promptly answer with a stale RRset if one is available in
* cache.
*/
qctx->options.stalefirst = (!qctx->is_zone &&
qctx->view->staleanswerclienttimeout == 0 &&
dns_view_staleanswerenabled(qctx->view));
result = query_lookup(qctx);
@ -5773,7 +5771,9 @@ query_lookup(query_ctx_t *qctx) {
rpzqname = qctx->client->query.qname;
}
if (qctx->options.stalefirst) {
qctx->client->query.dboptions &= ~DNS_DBFIND_STALETIMEOUT;
if (qctx->options.stalefirst && !qctx->is_zone) {
/*
* If the 'stalefirst' flag is set, it means that a stale
* RRset may be returned as part of this lookup. An attempt
@ -5937,8 +5937,6 @@ query_lookup(query_ctx_t *qctx) {
qctx_freedata(qctx);
dns_db_attach(qctx->client->view->cachedb,
&qctx->db);
qctx->client->query.dboptions &=
~DNS_DBFIND_STALETIMEOUT;
qctx->options.stalefirst = false;
if (FETCH_RECTYPE_NORMAL(qctx->client) != NULL)
{
@ -8570,11 +8568,9 @@ query_zone_delegation(query_ctx_t *qctx) {
* setting the 'stalefirst' option, which is usually set in
* the beginning in ns__query_start().
*/
if (qctx->view->staleanswerclienttimeout == 0 &&
dns_view_staleanswerenabled(qctx->view))
{
qctx->options.stalefirst = true;
}
qctx->options.stalefirst =
(qctx->view->staleanswerclienttimeout == 0 &&
dns_view_staleanswerenabled(qctx->view));
result = query_lookup(qctx);