From: Ondřej Surý Date: Thu, 6 Aug 2026 18:35:29 +0000 (+0200) Subject: Test a policy zone holding a record from outside the zone X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=002fa1cb494d56f9f73e36b1e015fbde8012c1d3;p=thirdparty%2Fbind9.git Test a policy zone holding a record from outside the zone Getting an out-of-zone record into a policy zone does not need a crafted transfer: lib/dns/master.c only drops such records for primaries, so a secondary keeps whatever its own copy of the zone contains. ns3 loads one that already holds "com.", which is the state a secondary reaches after a transfer that carried it, and is why the failure used to survive a restart with the primary gone. The checks read ns3's log rather than querying, so they do not depend on when the zone expires; a secondary's expiry runs from the mtime of the file it loaded, which for a file kept in the tree is whenever the tree was last touched. tests.sh fails on any "invalid rpz" complaint, which is how it catches unexpected ones, so the message this zone exists to provoke is excluded by name. Assisted-by: Claude:claude-opus-5 --- diff --git a/bin/tests/system/rpz/ns3/named.conf.j2 b/bin/tests/system/rpz/ns3/named.conf.j2 index a69dab160d6..2e5a916fe9c 100644 --- a/bin/tests/system/rpz/ns3/named.conf.j2 +++ b/bin/tests/system/rpz/ns3/named.conf.j2 @@ -37,6 +37,7 @@ options { zone "evil-cname" policy cname a12.tld2. ede blocked; zone "wild-cname" ede blocked; zone "slow-rpz"; + zone "outofzone.tld2"; } add-soa yes min-ns-dots 0 @@ -122,6 +123,18 @@ zone "fast-expire." { notify no; }; +/* + * A policy zone holding a record from outside the zone. ns2 does not + * serve it, so "outofzone.db" is never replaced by a transfer. + */ +zone "outofzone.tld2." { + type secondary; + file "outofzone.db"; + masterfile-format text; + primaries { 10.53.0.2; }; + notify no; +}; + zone "stub." { type stub; primaries { 10.53.0.2; }; diff --git a/bin/tests/system/rpz/ns3/outofzone.db.in b/bin/tests/system/rpz/ns3/outofzone.db.in new file mode 100644 index 00000000000..1bb3664db21 --- /dev/null +++ b/bin/tests/system/rpz/ns3/outofzone.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; A policy zone as a secondary would have written it out after a transfer +; that carried a record from outside the zone. The zone is a secondary so +; that this file is loaded the way a secondary loads its own copy of a +; transferred zone; the out-of-zone check in lib/dns/master.c only applies +; to primaries. + +$TTL 300 +@ SOA ns.tld3. hostmaster.ns.tld3. ( 1 3600 1200 2419200 60 ) + NS ns.tld3. + +; Two labels, fewer than the three of the origin, so stripping the origin +; from it used to underflow an unsigned label count in name2data(). +com. CNAME . + +; An ordinary trigger, so the test can tell that the rest of the zone is +; still loaded after the record above has been rejected. It is never +; queried, so it cannot disturb the other checks in this test. +never-queried.example CNAME . diff --git a/bin/tests/system/rpz/setup.sh b/bin/tests/system/rpz/setup.sh index eee949dd076..80d8ea4b7ca 100644 --- a/bin/tests/system/rpz/setup.sh +++ b/bin/tests/system/rpz/setup.sh @@ -48,6 +48,9 @@ cp ns3/slow-rpz.db.in ns3/slow-rpz.db cp ns5/fast-expire.db.in ns5/fast-expire.db cp ns5/expire.conf.in ns5/expire.conf +# a policy zone holding a record from outside the zone +cp ns3/outofzone.db.in ns3/outofzone.db + # $1=directory # $2=domain name # $3=input zone file diff --git a/bin/tests/system/rpz/tests.sh b/bin/tests/system/rpz/tests.sh index 82a7135ca10..ad295001070 100644 --- a/bin/tests/system/rpz/tests.sh +++ b/bin/tests/system/rpz/tests.sh @@ -659,12 +659,15 @@ if test -z "$HAVE_CORE"; then test -z "$HAVE_CORE" || setret "found $HAVE_CORE; memory leak?" fi -# look for complaints from lib/dns/rpz.c and bin/name/query.c +# look for complaints from lib/dns/rpz.c and bin/name/query.c, except the +# one the outofzone.tld2 policy zone is there to provoke +EXPECTED='invalid rpz owner name "com"' for runfile in ns*/named.run; do - EMSGS=$(nextpart $runfile | grep -E -l 'invalid rpz|rpz.*failed' || true) + EMSGS=$(nextpart $runfile | grep -Fv "$EXPECTED" \ + | grep -E -l 'invalid rpz|rpz.*failed' || true) if test -n "$EMSGS"; then setret "error messages in $runfile starting with:" - grep -E 'invalid rpz|rpz.*failed' ns*/named.run \ + grep -E 'invalid rpz|rpz.*failed' ns*/named.run | grep -Fv "$EXPECTED" \ | sed -e '10,$d' -e 's/^//' | cat_i fi done diff --git a/bin/tests/system/rpz/tests_rpz_outofzone.py b/bin/tests/system/rpz/tests_rpz_outofzone.py new file mode 100644 index 00000000000..1064acd7eed --- /dev/null +++ b/bin/tests/system/rpz/tests_rpz_outofzone.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from isctest.instance import NamedInstance + + +def test_rpz_out_of_zone_owner_name(ns3: NamedInstance) -> None: + """ + ns3 loads a policy zone holding "com.", whose two labels are fewer than + the three of the "outofzone.tld2." origin that gets stripped from an + owner name to build the trigger name. That used to underflow an + unsigned label count and fail an assertion, taking named down as the + policy zone was loaded - so reaching this test at all is most of the + check. + """ + assert 'invalid rpz owner name "com"; not within the policy zone' in ns3.log + + # Only the record above was dropped; the rest of the zone still loads. + assert ( + "rpz: outofzone.tld2: adding node never-queried.example.outofzone.tld2" + in ns3.log + ) diff --git a/bin/tests/system/rpz/tests_sh_rpz.py b/bin/tests/system/rpz/tests_sh_rpz.py index 348546f4c50..c1ee8caf3c3 100644 --- a/bin/tests/system/rpz/tests_sh_rpz.py +++ b/bin/tests/system/rpz/tests_sh_rpz.py @@ -45,6 +45,7 @@ pytestmark = pytest.mark.extra_artifacts( "ns3/mixed-case-rpz.db", "ns3/named.conf.tmp", "ns3/named.stats", + "ns3/outofzone.db", "ns3/slow-rpz.db", "ns3/wild-cname.db", "ns5/bl.db",