From f7cd00f1ef11950cf41cb58d9c7e701fb6568906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Wed, 29 Apr 2026 19:23:19 +0200 Subject: [PATCH] Fix swapped arguments in redirect2() single-label branch For a query whose qname is the root, the labels==1 branch in redirect2() called dns_name_copy(redirectname, view->redirectzone) with arguments reversed, overwriting the view-global nxdomain-redirect target with the empty redirectname rather than copying the configured target into the per-query lookup name. After the corruption, view->redirectzone names the root, so dns_name_issubdomain() makes redirect2() short-circuit for every subsequent query and the nxdomain-redirect feature stops working until named is restarted. Triggering this needs the resolver to receive an NXDOMAIN for the root from upstream, which does not happen in normal DNS operation. Swap the arguments to match the dns_name_copy(source, dest) signature. Add a system test that issues a root query through the nxdomain-redirect resolver and verifies the redirect feature still works for a normal NXDOMAIN-producing query afterwards. Assisted-by: Claude:claude-opus-4-7 (cherry picked from commit c62f24f7eea4447609e4e3f14773ae7a1beb6709) --- bin/tests/system/redirect/tests.sh | 10 ++++++++++ lib/ns/query.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/bin/tests/system/redirect/tests.sh b/bin/tests/system/redirect/tests.sh index 5d074907f3..007b6f73de 100644 --- a/bin/tests/system/redirect/tests.sh +++ b/bin/tests/system/redirect/tests.sh @@ -542,6 +542,16 @@ n=$((n + 1)) if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) +echo_i "checking nxdomain-redirect survives query for root ($n)" +ret=0 +$DIG $DIGOPTS . any @10.53.0.4 -b 10.53.0.2 >dig.out.ns4.test$n.a || ret=1 +$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 a >dig.out.ns4.test$n.b || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n.b >/dev/null || ret=1 +grep "nonexist. .*100.100.100.1" dig.out.ns4.test$n.b >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + echo_i "checking extended error is not set on allow-recursion ($n)" ret=0 $DIG $DIGOPTS example. @10.53.0.1 -b 10.53.0.2 soa >dig.out.ns1.test$n || ret=1 diff --git a/lib/ns/query.c b/lib/ns/query.c index e28357cd06..91f2292db8 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -5127,7 +5127,7 @@ redirect2(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset, return ISC_R_NOTFOUND; } } else { - dns_name_copy(redirectname, client->view->redirectzone); + dns_name_copy(client->view->redirectzone, redirectname); } options = 0;