Commit graph

44434 commits

Author SHA1 Message Date
Nicki Křížek
9a420bde2f Add private_key support to all ZoneKey implementations
Extend the ZoneKeyFile to read the file-backed private key and return it
in a format suitable for use with dnspython. Add ZoneKey.private_key
property to unify the interface.

(cherry picked from commit ee73ba3bba)
2026-07-02 15:45:49 +02:00
Nicki Křížek
a7c9dfe169 Use the algorithm.number interface 2026-07-02 15:45:49 +02:00
Nicki Křížek
9d5b97db80 Add NSEC3RSASHA1 to list of algorithms
This algorithm is deprecated and not currently used in our system tests,
but it should be in the list of all algorithms.

(cherry picked from commit 596e41553c)
2026-07-02 15:45:49 +02:00
Nicki Křížek
cad0939602 Move dnskey method from kasp.Key to zone.FileZoneKey
Code move with one change - switch dnskey TTL from 300s (DEFAULT_TTL) to
3600s (DNSKEY_TTL).

Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit 55cd4a1e11)
2026-07-02 15:45:49 +02:00
Nicki Křížek
df7e8cf6bb Merge kasp.Key functionality into zone.FileZoneKey
Make zone.FileZoneKey the single representation of a file-backed key
(typically generated by dnssec-keygen). Move the common key-related
functionality into zone.FileZoneKey, and extend that functionality in
kasp.Key to also add state and timing related operations on top. Remove
duplicate into_ta() function.

Note that is_ksk() is implemented differently for kasp.Key: with the
metadata file available, the KSK status is loaded from that file, as it
indicates the authoritative policy decision which makes the key a KSK.
In zone.FileZoneKey which doesn't work with the metadata file, the KSK
status if inferred from the DNSKEY SEP flag - the best information
available for that class.

Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit 35fc5ce8b4)
2026-07-02 15:45:49 +02:00
Nicki Křížek
c5f4d66e73 Read DNSKEY TTL from kasp.Key.dnskey
Remove the redundant ttl() method. The DNSKEY RR already provides the
TTL.

(cherry picked from commit 9dc039f735)
2026-07-02 15:45:49 +02:00
Michał Kępień
2817844b80 [9.20] chg: test: Update AsyncDnsServer-related test cookbook parts
Add practical tips about specific handler classes.  Mention some good
practices and point developers at existing code written in the desired
manner.  Document common pitfalls.  Suggest preferred approaches for
splitting up complex response handling code.

Backport of MR !12260

Merge branch 'backport-michal/update-asyncdnsserver-related-test-cookbook-parts-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12352
2026-07-02 15:18:46 +02:00
Michał Kępień
3665c94e56
Move ans.py-related information to README.md
COOKBOOK.md is supposed to be minimal and heavy on examples, so move the
lengthy section about implementing custom ans.py servers from
COOKBOOK.md to README.md.

(cherry picked from commit edd765a092)
2026-07-02 15:17:03 +02:00
Michał Kępień
1072686f46
Update AsyncDnsServer-related test cookbook parts
Add practical tips about specific handler classes.  Mention some good
practices and point developers at existing code written in the desired
manner.  Document common pitfalls.  Suggest preferred approaches for
splitting up complex response handling code.

(cherry picked from commit a48e5cd98d)
2026-07-02 15:17:03 +02:00
Alessio Podda
cdbc5be8b0 [9.20] fix: usr: Reject external referrals from forwarders
Under `forward-first` policy in a forwarding zone BIND could accept NS above the forward zone apex from negative responses. This has been fixed.

ISC would like to thank Qifan Zhang, of Palo Alto Networks, for the report.

Closes #5937

Backport of MR !12154

Merge branch 'backport-5937-fix-forward-first-referral-bailiwick-v2-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12278
2026-07-02 12:26:26 +00:00
Alessio Podda
a0b2777ba5 Reject referrals from global forwarders
Reject referrals from root/global forwarders, where there is no narrower
forward-zone apex for name_external() to enforce.

(cherry picked from commit 18f4db8f1b)
2026-07-02 11:50:20 +00:00
Alessio Podda
4d97a40a97 Reject external referrals for forward zones
Apply the existing name_external() bailiwick check to NS RRsets
processed as referrals in rctx_authority_negative(), and enforce the
same check again in rctx_referral() before caching or following the
delegation.

This prevents a forward-first forwarder from installing a parent
zone-cut above the configured forward zone via an authority-section
NS RRset.

(cherry picked from commit 492d11fa39)
2026-07-02 11:50:20 +00:00
Alessio Podda
8e546f019f Add forward-first referral poisoning reproducer
Add a system test covering authority-section NS referrals returned by
configured forwarders under forward first.

The test verifies that a forwarder for fwd.hack cannot install the
parent hack zone cut and redirect resolution for the sibling zone
sibling.hack.

(cherry picked from commit ee34bbd208)
2026-07-02 11:50:20 +00:00
Ondřej Surý
8a8cc34a50 [9.20] fix: dev: Correct locator decoding for NID, L64, and L32 records
NID, L64, and L32 records were decoded incorrectly when converted into their
parsed structures, because the preference field was not skipped before the
locator.

Closes #6097

Backport of MR !12348

Merge branch 'backport-6097-nid-l64-l32-tostruct-consume-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12349
2026-07-02 13:31:51 +02:00
Ondřej Surý
4e6028883d Add NID/L64/L32 round-trip coverage to the rdata unit test
These types had no entries in the rdata test table, so the
tostruct/fromstruct round-trip in check_struct_conversions() never ran
against them -- which is why the missing preference consume in their
tostruct routines went unnoticed for years. Add text and wire vectors
for all three.

Assisted-by: Claude:claude-fable-5
(cherry picked from commit f28bea94e3)
2026-07-02 10:55:30 +00:00
Ondřej Surý
815587fbe6 Consume the preference before reading the locator in NID/L64/L32 tostruct
tostruct_nid() and tostruct_l64() read the 16-bit preference with the
non-consuming uint16_fromregion() and then memmove()'d the whole
remaining region -- still ten octets, still anchored at the preference
-- into the eight-octet nid[]/l64[] arrays. That folded the preference
into the first two locator octets and stored two octets past the end of
the array. tostruct_l32() shares the root cause: it read the 32-bit
locator from the same unconsumed offset, so the value was built from the
preference plus the first two locator octets.

Consume the two preference octets first, matching the sibling
tostruct_lp(), and assert the expected framing on the fixed-size types.

(cherry picked from commit 5aa279bbea)
2026-07-02 10:55:30 +00:00
Ondřej Surý
73440816e4 [9.20] fix: dev: Fix a memory leak when updating a zone with more than 32 DNSSEC keys
Applying changes to a signed zone — via DNS UPDATE or the inline-signing
raw-to-secure sync — leaked the surplus keys when the zone's key
directory held more than 32, slowly growing named's memory use.

Closes #6051

Backport of MR !12328

Merge branch 'backport-6051-find-zone-keys-key-leak-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12332
2026-07-01 14:05:30 +02:00
Ondřej Surý
fc1055d539 Add a regression test for the find_zone_keys() key leak
Generate more than DNS_MAXZONEKEYS distinct matching private keys for a
zone and call find_zone_keys() through it.  The keys past the limit must
be released; the default memory context's leak check, armed with
isc_mem_checkdestroyed(), fails the test if any are abandoned.

Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit 3d0c452cad)
2026-07-01 14:04:36 +02:00
Ondřej Surý
8e02a2bc38 Stop leaking DNSSEC keys past the zone key limit
find_zone_keys() collects every matching private key into a local list,
hands the first DNS_MAXZONEKEYS keys to the caller, and frees the rest.
On overflow it destroyed only the first surplus key before breaking out
of the loop, so any keys after it stayed linked on the local list and
were lost when the function returned.

Unlink and destroy every list entry, transferring a key to the caller
only while under the limit.  No entry is left behind, so a zone with
more than DNS_MAXZONEKEYS matching keys no longer leaks memory on each
signing attempt.

(cherry picked from commit a957dd13fa)
2026-07-01 14:04:36 +02:00
Ondřej Surý
af19f1a109 [9.20] chg: doc: Add non-IN RR classes to list of unsupported configurations
This adds a note to the security documentation that configuring
resources with non-Internet DNS classes (CHAOS, HESIOD, ...) is not
a supported configuration and could potentially cause issues.

Closes #5805

Backport of MR !11667

Merge branch 'backport-5805-add-clarification-on-non-IN-classes-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12334
2026-07-01 13:19:45 +02:00
Ondřej Surý
1af9f28301
Document that non-IN RR class issues are out of CVE scope
CVE-2026-5946 covered assertion failures reachable only through the
handling of resource record classes other than Internet (IN).
Configuring zones or views with such classes is a supported feature;
document in the security assumptions that problems reachable only
through it cannot be the basis for CVE assignment.

Closes #5805

Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit fc06f799dc)
2026-07-01 13:13:48 +02:00
Ondřej Surý
fb0ae8a5d6 [9.20] fix: usr: Stop reusing outgoing TCP connections the peer has already closed
``named`` could hand a new query an idle forwarder/upstream TCP or TLS
connection that the peer had already closed, causing the query to fail
(and CLOSE-WAIT sockets to pile up). Idle reused connections are now
watched, so a close is noticed and the connection is dropped instead of
reused. A new ``tcp-reuse-timeout`` option controls how long an idle
outgoing connection is kept open for reuse (default 5 seconds).

Closes #6171

Backport of MR !8972, !9698, !9927, and !12289

Merge branch 'backport-6171-tcp-reuse-idle-read-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12317
2026-06-25 11:38:03 +02:00
Ondřej Surý
173255127f Add the tcp-reuse-timeout option
The idle timeout that bounds how long a reused outgoing TCP/TLS
connection is held open for reuse was only tunable through the 'named -T
tcpidletimeout' developer hook added earlier on this branch. Make it a
proper configuration option, tcp-reuse-timeout (options block, in units
of 100 milliseconds like the other tcp-*-timeout options), and drop the
-T hook.

(cherry picked from commit 477130cf8e)
2026-06-25 11:37:51 +02:00
Aram Sargsyan
89b92a070c Use a suitable response in tcp_connected() when initiating a read
When 'ISC_R_TIMEDOUT' is received in 'tcp_recv()', it times out the
oldest response in the active responses queue, and only after that it
checks whether other active responses have also timed out. So when
setting a timeout value for a read operation after a successful
connection, it makes sense to take the timeout value from the oldest
response in the active queue too, because, theoretically, the responses
can have different timeout values, e.g. when the TCP dispatch is shared.
Currently 'resp' is always NULL. Previously when connect and read
timeouts were not separated in dispatch this affected only logging, but
now since we are setting a new timeout after a successful connection,
we need to choose a suitable response from the active queue.

(cherry picked from commit e61ba5865f)
(partially cherry-picked from commit 64ffbe82c0)
2026-06-25 11:37:51 +02:00
Michał Kępień
1783d311e6 Improve reuse of outgoing TCP connections
The dns_dispatch_gettcp() function is used for finding an existing TCP
connection that can be reused for sending a query from a specified local
address to a specified remote address.  The logic for matching the
provided <local address, remote address> tuple to one of the existing
TCP connections is implemented in the dispatch_match() function:

  - if the examined TCP connection already has a libuv handle assigned,
    it means the connection has already been established; therefore,
    compare the provided <local address, remote address> tuple against
    the corresponding address tuple for the libuv handle associated with
    the connection,

  - if the examined TCP connection does not yet have a libuv handle
    assigned, it means the connection has not yet been established;
    therefore, compare the provided <local address, remote address>
    tuple against the corresponding address tuple that the TCP
    connection was originally created for.

This logic limits TCP connection reuse potential as the libuv handle
assigned to an existing dispatch object may have a more specific local
<address, port> tuple associated with it than the local <address, port>
tuple that the dispatch object was originally created for.  That's
because the local address for outgoing connections can be set to a
wildcard <address, port> tuple (indicating that the caller does not care
what source <address, port> tuple will be used for establishing the
connection, thereby delegating the task of picking it to the operating
system) and then get "upgraded" to a specific <address, port> tuple when
the socket is bound (and a libuv handle gets associated with it).  When
another dns_dispatch_gettcp() caller then tries to look for an existing
TCP connection to the same peer and passes a wildcard address in the
local part of the tuple, the function will not match that request to a
previously-established TCP connection (unless isc_nmhandle_localaddr()
returns a wildcard address as well).

Simplify dispatch_match() so that the libuv handle associated with an
existing dispatch object is not examined for the purpose of matching it
to the provided <local address, remote address> tuple; instead, always
examine the <local address, remote address> tuple that the dispatch
object was originally created for.  This enables reuse of TCP
connections created without providing a specific local socket address
while still preventing other connections (created for a specific local
socket address) from being inadvertently shared.

(cherry picked from commit 086c325ad3)
2026-06-25 11:37:51 +02:00
Ondřej Surý
dc78507aa0 Keep idle reused outgoing TCP connections under read
A reused TCP/TLS dispatch with no outstanding responses was left in the
reuse pool with no read pending, so a peer closing the idle connection
went unnoticed: the socket lingered in CLOSE-WAIT and the dead dispatch
was later handed to a new query, which failed and the fetch timed out.
Keep a read pending on an idle connected dispatch, bounded by an idle
timeout, so the close is seen promptly and the connection is dropped
from the pool instead of reused.

The idle read may only be (re)armed while the dispatch is still
connected; arming it on a dispatch that is already shutting down
re-reads a dying handle and double-schedules a netmgr job.

On shutdown, close the connection as soon as the dispatch reaches its
terminal state instead of waiting for the last reference to drop, so an
unexpected read (or a peer-side close) cannot leave the socket in
CLOSE-WAIT while a reference still lingers.

(cherry picked from commit febeac215d)
2026-06-25 11:37:51 +02:00
Mark Andrews
ed27fb9524 [9.20] fix: usr: Tighten referral DS acceptance
Named was accepting DS records for sibling zones when it shouldn't
have.  This has been fixed.

Closes #5870

Backport of MR !11837

Merge branch 'backport-5870-tighten-referral-ds-acceptance-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12325
2026-06-25 16:44:26 +10:00
Nicki Křížek
7f86813245 Add dnssec_py/tests_sibling_ds: reject DS for sibling zones in referrals
Add a system test that verifies the resolver rejects DS records whose
owner name does not match the delegation (NS) name in a referral
response.

A custom authoritative server (ans4) serves the parent zone sibling-ds.
from zone file with delegations for child and sibling subzones.  Its
DomainHandler injects a DS record for sibling.sibling-ds into referrals
for child.sibling-ds.  The resolver must detect the mismatch, log "DS
doesn't match referral (NS)", and return SERVFAIL.

Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit a2b9dcff54)
2026-06-25 06:05:02 +00:00
Nicki Křížek
e9912d3ea5 Don't include ORIGIN for AsyncDnsServer zones
The zone template can't use $ORIGIN with AsyncDnsServer because
AsyncDnsServer._load_zone_file_with_origin() rejects it for non-root
zones.

(cherry picked from commit 95a268f119)
2026-06-25 06:05:02 +00:00
Mark Andrews
1d39ec0bf4 Tighten referral DS acceptance
Named was accepting DS records for sibling zones when it shouldn't
have.  Only DS rrsets that match the delegation name should have
been accepted.

Remove ds_name from struct respctx as it is no longer useful.

(cherry picked from commit 123934931f)
2026-06-25 06:05:02 +00:00
Evan Hunt
2afca83414 [9.20] fix: usr: Check that an NSEC signer is at or above the name to be validated
Add a check that an NSEC record being used as a proof of nonexistence
for a given name is not signed by a name lower in the DNS hierarchy than
the one in question.

Closes #5876

Backport of MR !12272

Merge branch 'backport-5876-nsec-signer-above-name-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12324
2026-06-24 21:50:27 +00:00
Alessio Podda
4802beb762 Reproducer for #5876 child apex self-loop NSEC
Added to "nsec_synthesis" system test.

Co-Authored-By: Evan Hunt <each@isc.org>
(cherry picked from commit 4fb662a171)
2026-06-24 21:50:08 +00:00
Evan Hunt
d3c85737f7 Check that an NSEC signer is at or above the name to be validated
Add a check that an NSEC record being used as a proof of nonexistence
for a given name is not signed by a name lower in the DNS hierarchy than
the one in question.

Fixes: isc-projects/bind9#5876

(cherry picked from commit c5f99f3508)
2026-06-24 21:50:08 +00:00
Štěpán Balážik
93aa52442a [9.20] chg: test: Reimplement the formerr system test in Python
Replace the shell and Perl based FORMERR system test with a Python
test that constructs the malformed DNS packets directly and checks
the responses.

Remove the legacy shell and Perl test script and the intermediate
packet files in hex, leaving the packet construction inline in
tests_formerr.py.

Backport of MR !11898

Merge branch 'backport-stepan/formerr-system-test-python-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12270
2026-06-24 21:33:47 +00:00
Štěpán Balážik
62cfb8bdae Simplify the packets in the formerr system test
Normalize the message ID to 0 and the TTL of records to 1 unless
required (OPT and UPDATE records require TTL=0).

Rename the questionclass test case to twoquestionclasses for
consistency.

(cherry picked from commit 62a3804a4c)
2026-06-24 22:22:35 +02:00
Štěpán Balážik
28e0c79b12 Reimplement the FORMERR system test in Python
Replace the shell and Perl based FORMERR system test with a Python
test that constructs the malformed DNS packets directly and checks
the responses.

Remove the legacy shell and Perl test script and the intermediate
packet files in hex, leaving the packet construction inline in
tests_formerr.py.

Preserve the same wire for all packets sent to the server, but
construct them in a more explicit and readable way.

(cherry picked from commit 151b2d6045)
2026-06-24 22:22:35 +02:00
Michal Nowak
95eb81bf1c [9.20] new: ci: Add Alpine Linux 3.24
Backport of MR !12229

Merge branch 'backport-mnowak/alpine-3.24-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12321
2026-06-24 18:44:43 +02:00
Michal Nowak
8ce39fdcb1 Fix a false positive compiler warning/error on Alpine 3.24
On Alpine Linux 3.24, GCC 15 with fortify-headers produces a compiler
warning when building bin/nsupdate/nsupdate.c:

    In function 'fgets',
        inlined from 'get_next_command' at ../bin/nsupdate/nsupdate.c:2414:13:
    /usr/include/fortify/stdio.h:48:16: error: 'cmdlinebuf' may be used uninitialized [-Werror=maybe-uninitialized]
       48 |         return __orig_fgets(__s, __n, __f);
          |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/include/fortify/stdio.h:42:1: note: in a call to '*fgets' declared with attribute 'access (read_write, 1, 2)' here
       42 | _FORTIFY_FN(fgets) char *fgets(char * _FORTIFY_POS0 __s, int __n, FILE *__f)
          | ^~~~~~~~~~~
    ../bin/nsupdate/nsupdate.c:2405:14: note: 'cmdlinebuf' declared here
     2405 |         char cmdlinebuf[MAXCMD];
          |              ^~~~~~~~~~

This is a false positive, because fgets() only writes into the buffer;
the fortify-headers wrapper annotates the buffer argument with
'access (read_write, ...)', which makes GCC treat passing an
uninitialized buffer as a read of uninitialized memory.

Initialize the 'cmdlinebuf' buffer anyway to avoid the build error.

Assisted-by: Claude:claude-fable-5
(cherry picked from commit 62670aa1b7)
2026-06-24 18:06:47 +02:00
Michal Nowak
c2b901d5e5 Add Alpine Linux 3.24
(cherry picked from commit 774a9661fc)
2026-06-24 18:06:47 +02:00
Michal Nowak
b3e335df63 [9.20] fix: test: Retry pipequeries on a transient EADDRINUSE in the pipelined test
On FreeBSD, the TCP connect() call can transiently fail with
EADDRINUSE under parallel CI load.  The netmgr already retries such
connects (see #3451), but it retries on the same socket, which is
already bound to the same ephemeral source port, so when the
four-tuple is genuinely busy (e.g. in TIME_WAIT) every retry fails
the same way.  pipequeries then exits with "request event result:
address in use", leaving raw.1 empty and failing the first check.

All eight requests share a single TCP dispatch, so the failed connect
means no query ever reached ns4 and its cache is still cold.  It is
therefore safe to run pipequeries again: a fresh process binds a new
ephemeral port, and the out-of-order check keeps its meaning.  Retry
for up to ten attempts, but only on this specific transient error.

Assisted-by: Claude Code:claude-fable-5

Backport of MR !12228

Merge branch 'backport-mnowak/pipelined-retry-transient-eaddrinuse-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12320
2026-06-24 18:06:10 +02:00
Michal Nowak
28142e98a5 Retry pipequeries on a transient EADDRINUSE in the pipelined test
On FreeBSD, the TCP connect() call can transiently fail with
EADDRINUSE under parallel CI load.  The netmgr already retries such
connects (see #3451), but it retries on the same socket, which is
already bound to the same ephemeral source port, so when the
four-tuple is genuinely busy (e.g. in TIME_WAIT) every retry fails
the same way.  pipequeries then exits with "request event result:
address in use", leaving raw.1 empty and failing the first check.

All eight requests share a single TCP dispatch, so the failed connect
means no query ever reached ns4 and its cache is still cold.  It is
therefore safe to run pipequeries again: a fresh process binds a new
ephemeral port, and the out-of-order check keeps its meaning.  Retry
for up to ten attempts, but only on this specific transient error.

Assisted-by: Claude:claude-fable-5
Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit b9cf877277)
2026-06-24 18:05:46 +02:00
Michal Nowak
5bb30b1f99 [9.20] new: dev: Print OS platform in "named -V"
The "running on" line emitted by `named -V` (as well as the startup
log and `rndc status`, which share the same source) now appends the
PRETTY_NAME value from /etc/os-release in parentheses after the uname
output, e.g.:

    running on Linux x86_64 6.19.14-... (Fedora Linux 42 (Workstation Edition))

This helps disambiguate environments where the kernel string is not a
reliable indicator of the userspace, such as RHEL clones and
containers whose kernel does not match the host OS.

When /etc/os-release is absent, /usr/lib/os-release is tried as a
fallback per the systemd os-release(5) specification. When neither is
available or no PRETTY_NAME is found, the output is unchanged.

Assisted-by: Claude:claude-opus-4-7

Closes #5334

Backport of MR !12055

Merge branch 'backport-5334-add-os-platform-to-named-V-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12319
2026-06-24 17:52:57 +02:00
Michal Nowak
20197027a1 Print OS platform in "named -V"
The "running on" line emitted by `named -V` (as well as the startup
log and `rndc status`, which share the same source) now appends the
PRETTY_NAME value from /etc/os-release in parentheses after the uname
output, e.g.:

    running on Linux x86_64 6.19.14-... (Fedora Linux 42 (Workstation Edition))

This helps disambiguate environments where the kernel string is not a
reliable indicator of the userspace, such as RHEL clones and
containers whose kernel does not match the host OS.

When /etc/os-release is absent, /usr/lib/os-release is tried as a
fallback per the systemd os-release(5) specification. When neither is
available or no PRETTY_NAME is found, the output is unchanged.

Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit b5ca9d3372)
2026-06-24 17:52:30 +02:00
Ondřej Surý
d9640a3a0b [9.20] new: test: Add extra expired RRSIGs test to dnssec_py
Related #5760

Backport of MR !11808

Merge branch 'backport-nicki/pytest-add-extra-expired-rrsigs-test-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12318
2026-06-24 17:14:40 +02:00
Nicki Křížek
0c5242925d Add extra expired RRSIGs test to dnssec_py
The test verifies that a validating resolver enforces the
max-validations-per-fetch limit when encountering a record with multiple
expired RRSIGs followed by a valid one. One of the records is signed
three times: twice with expired timestamps (to produce two expired
RRSIGs for a.rrsigs-extra-expired/A) and once with valid timestamps,
after which the expired RRSIGs are injected back into the signed zone
file. max-validations-per-fetch is set to 2 via the template variable so
that the third (valid) RRSIG is never reached, causing SERVFAIL.

Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit fe2fea73a4)
2026-06-24 14:32:46 +00:00
Ondřej Surý
51d7456399 [9.20] fix: dev: Fix a possible crash when cleaning up a view's caches
In rare cases named could crash while a view was being removed, for example
during reconfiguration or shutdown, as its internal caches were torn down.
This has been fixed.

Closes #6119

Backport of MR !12177

Merge branch 'backport-6119-fix-possible-uaf-when-destroying-dns_badcache-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12190
2026-06-24 15:50:08 +02:00
Ondřej Surý
5df459bcde Fix use-after-free when destroying the bad and unreachable caches
Eviction of an entry owned by another loop was bounced to that loop via
isc_async_run(), so a queued list removal could run after the cache had
freed its LRU lists.  Use a single mutex-guarded LRU list instead, removing
entries synchronously under the lock, and let each entry hold its own
memory-context reference so the RCU free never touches a gone loop.

(cherry picked from commit bb43ecaf51)
2026-06-24 15:49:56 +02:00
Ondřej Surý
5fe742e3fd [9.20] fix: dev: Fix invalid pointer release in JSON statistics-channel response
Each response served on a JSON statistics endpoint released the wrong
pointer to the JSON library after the response was sent: the response
body string instead of the JSON document.  With the current responses
this does not crash named in practice, but the call is incorrect and
can in principle corrupt memory.  XML responses are not affected.

Closes #6024

Backport of MR !12068

Merge branch 'backport-6024-statschannel-json-response-invalid-free-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12274
2026-06-24 15:39:39 +02:00
Ondřej Surý
4467823700 Fix invalid free in statistics-channel JSON renderer
wrap_jsonfree() called json_object_put() on the response-body buffer
base, which is the JSON string returned by
json_object_to_json_string_ext(), not a struct json_object.  The root
object is already passed in as the callback argument; release only
that.

(cherry picked from commit f39089576a)
2026-06-24 15:39:24 +02:00
Ondřej Surý
b2f4b8af32 Add regression test for statistics-channel JSON free bug
Hit every JSON statistics endpoint several times.  The current code
calls json_object_put() on the response-body string pointer, which
doesn't crash just by accident - the memory position contains large
value from static string.

(cherry picked from commit 9608158d73)
2026-06-24 15:39:24 +02:00