[9.20] [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.

Backport of !808

See isc-projects/bind9#5372

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

See merge request isc-private/bind9!815
This commit is contained in:
Michał Kępień 2025-07-03 14:17:14 +02:00
commit 055a592fd9

View file

@ -5920,16 +5920,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);
@ -6058,7 +6056,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
@ -6222,8 +6222,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)
{
@ -8948,11 +8946,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);