diff --git a/CHANGES b/CHANGES index c88380912f..aa7dc35903 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +5591. [bug] Fix a crash happening when "stale-answer-client-timeout" + is triggered and there is no (stale) data for it in the + cache. [GL #2503] + 5590. [bug] Process NSEC3PARAM queue when loading a dynamic zone. This will immediately create NSEC3 records for zones that use "dnssec-policy" and "nsec3param". [GL #2498] diff --git a/bin/tests/system/serve-stale/tests.sh b/bin/tests/system/serve-stale/tests.sh index a11319c854..8ca4cf1511 100755 --- a/bin/tests/system/serve-stale/tests.sh +++ b/bin/tests/system/serve-stale/tests.sh @@ -1068,11 +1068,22 @@ status=$((status+ret)) sleep 2 +# Check that if we don't have stale data for a domain name, we will +# not answer anything until the resolver query timeout. +n=$((n+1)) +echo_i "check notincache.example times out (max-stale-ttl default) ($n)" +ret=0 +$DIG -p ${PORT} +tries=1 +timeout=3 @10.53.0.3 notfound.example TXT > dig.out.test$n 2>&1 +grep "connection timed out" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + echo_i "sending queries for tests $((n+1))-$((n+4))..." $DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$((n+1)) & $DIG -p ${PORT} @10.53.0.3 othertype.example CAA > dig.out.test$((n+2)) & $DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$((n+3)) & -$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$((n+4)) +$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$((n+4)) & +$DIG -p ${PORT} @10.53.0.3 notfound.example TXT > dig.out.test$((n+5)) wait @@ -1112,6 +1123,16 @@ grep "example\..*30.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) +# The notfound.example check is different than nxdomain.example because +# we didn't send a prime query to add notfound.example to the cache. +n=$((n+1)) +echo_i "check notfound.example (max-stale-ttl default) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + # # Now test server with serve-stale answers disabled. # diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 54733d22c3..1ee8b09025 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -59,3 +59,8 @@ Bug Fixes - An invalid direction field (not one of 'N'/'S' or 'E'/'W') in a LOC record triggered an INSIST failure. [GL #2499] + +- Previously, a BIND server could experience an unexpected server termination + (crash) if the return of stale cached answers was enabled and + ``stale-answer-client-timeout`` was applied to a client query in process. + This has been fixed. [GL #2503] diff --git a/lib/ns/query.c b/lib/ns/query.c index 9d5844084f..52e40922c9 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -5972,6 +5972,15 @@ query_lookup(query_ctx_t *qctx) { } } } + } else if (stale_only && result != ISC_R_SUCCESS) { + /* + * This is a staleonly lookup and no stale answer was found + * in cache. Treat as we don't have an answer and wait for + * the resolver fetch to finish. + */ + if ((qctx->options & DNS_GETDB_STALEFIRST) == 0) { + return (result); + } } else { stale_only = false; } @@ -6017,13 +6026,13 @@ query_lookup_staleonly(ns_client_t *client) { qctx_init(client, NULL, client->query.qtype, &qctx); dns_db_attach(client->view->cachedb, &qctx.db); + client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK; client->query.dboptions |= DNS_DBFIND_STALEONLY; (void)query_lookup(&qctx); if (qctx.node != NULL) { dns_db_detachnode(qctx.db, &qctx.node); } qctx_freedata(&qctx); - client->query.dboptions &= ~DNS_DBFIND_STALEONLY; qctx_destroy(&qctx); }