Commit graph

399 commits

Author SHA1 Message Date
Ondřej Surý
ddd5586a51
Make isc_mem_isovermem() probabilistic
Replace the hysteretic hi_water/lo_water switch with a stochastic
check: always false below lo_water, always true at or above hi_water,
linearly ramped probability in between.  This spreads cache cleaning
across many inserts instead of triggering a thundering herd once the
hi_water mark is crossed (which causes every addrdataset to enter the
LRU purge path simultaneously and serializes lookups behind the node
write locks).

The is_overmem atomic and its stores are no longer needed and are
removed.  The existing tests that asserted specific hysteretic state
transitions are simplified to check only the deterministic boundaries.

(cherry picked from commit ee24d2a1c3361dcc1c48fb29bb2e0b91bc3405e8)
2026-05-07 13:09:18 +02:00
Ondřej Surý
d35bc843c5 Implement seamless TCP connection reuse in dns_dispatch
Previously, the user of dns_dispatch API had to first call
dns_dispatch_gettcp() and if that failed create a new TCP dispatch with
dns_dispatch_createtcp().  This has been changed and the TCP connection
reuse happens transparently inside dns_dispatch_createtcp().  There are
separate buckets for dns_resolver, dns_request and dns_xfrin units, so
these don't get mixed together.

(cherry picked from commit d5ee86b799)
2026-05-06 15:05:48 +02:00
Ondřej Surý
2bbbd60de3
Reject oversized RRsets at slab construction
dns_rdataslab_fromrdataset(), dns_rdataslab_merge() and
dns_rdataslab_subtract() summed per-record storage into an
unsigned int with no upper-bound check.  An RRset whose total
encoded size exceeds DNS_RDATA_MAXLENGTH cannot fit in a DNS
message and is unservable; building its in-memory representation
only burns memory on data that will fail at response time, and at
the upper bound the running sum could in theory wrap.

Cap the running total at DNS_RDATA_MAXLENGTH and return ISC_R_NOSPACE
when exceeded.  Update the qpdb cache memory-purge test to use a
record size that fits within the new limit.

Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit f9d24b1b85)
2026-05-05 19:24:29 +02:00
Ondřej Surý
2b18aa9d59 Reject RSA DNSKEYs with oversize public exponents at parse time
The wire-format RSA DNSKEY parser was the only key path with no upper
bound on the public exponent — opensslrsa_parse and opensslrsa_fromlabel
already cap at RSA_MAX_PUBEXP_BITS.  An attacker-controlled DNSKEY could
therefore force a validator to compute s^e mod n with e up to ~|n| bits,
amplifying every verify by ~120x for typical 2048-bit moduli (OpenSSL
itself only caps the exponent for moduli above 3072 bits).  Apply the
same bit-count cap to wire-format keys.

Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit ab8c1a77e0)
2026-04-30 13:16:30 +02:00
Mark Andrews
9be3bccf6d Test the ability to walk the iterators multiple times
It should be possible to walk APL, HIP, HTTPS and SVBC record
elements multiple times.  We now test this.

(cherry picked from commit aa2a41b2d1)
2026-03-27 12:45:25 +00:00
Mark Andrews
6159980235 Test walking apl list entries
(cherry picked from commit e435b0b7fb)
2026-03-27 12:38:01 +00:00
Aram Sargsyan
77d60acb86 Convert dns_dtenv_t reference counting to standard macors
Use standard reference counting macros for dns_dtenv_t instead of
custom attach/detach functions.

(cherry picked from commit 4ac3a6520e)
2026-03-18 17:04:56 +00:00
Ondřej Surý
d4b96af062
Enforce isc_work enqueue loop affinity
Add a REQUIRE(isc_loop() == loop) assertion to isc_work_enqueue()
to strictly enforce that work is enqueued from the loop it is
assigned to. This loudly prohibits cross-thread queue manipulation
before it inevitably turns into a concurrency debugging nightmare.

(cherry picked from commit f1311d2d19)
2026-03-14 07:52:56 +01:00
Michal Nowak
82991c7881
Use clang-format-22 to update formatting
(cherry picked from commit 239464f276)
2026-03-04 12:18:27 +01:00
Mark Andrews
a38d599260 Test maximum length NSEC3 hash detection
Adds text and wire format unit tests to verify the newly enforced
maximum NSEC3 hash length constraints.  These tests ensure that hash
lengths up to the 39-byte maximum are accepted, while larger sizes
correctly fail.

(cherry picked from commit e83a182056)
2026-02-24 17:10:52 +01:00
Mark Andrews
c88aa8a380 Enforce NSEC3 record consistency
NSEC3 hashes are required to fit within a single DNS label.  Since there
are 5 bits per label byte without pad characters, the maximum hash size
is floor(63*5/8) (39 bytes).

This patch enforces this maximum length for unknown algorithms, while
strictly enforcing the exact expected digest length for known algorithms
like SHA-1.

(cherry picked from commit 3801d0ebbf)
2026-02-24 17:10:52 +01:00
Matthijs Mekking
440ada653d Add a regression test for the BRID/HHIT crash
Add two short records to example.com.db that cause assertion failures
when converted to wire form.

The checks added to tests.sh are technically not required: the relevant
assertion failures are already hit when the zone is transferred out of
ns1.

Update the relevant unit tests with 1-byte records.

Co-authored-by: Mark Andrews <marka@isc.org>
(cherry picked from commit ce1d68cbc5)
2026-02-05 18:23:49 +00:00
Alessio Podda
97f2816947 Fix formatting
Cleanup formatting after IXFR changes.

(cherry picked from commit ad0a382092)
2026-02-02 10:32:38 +01:00
Alessio Podda
62a8d325bd Add unit tests
Add diffop unit tests.

(cherry picked from commit fb72ebcdd8)
2026-02-02 10:32:38 +01:00
Alessio Podda
0a5e27deef Implement qpzone specific update path
This commit implements a batch update function for qpzone. The main
reason for this is speed: using addrdataset would cause a qp transaction
per rrdataset added, leading to a substantial slowdown compared to
RBTDB. The new API results in a qp transaction per applied diff.

(cherry picked from commit da53708dcb)
2026-02-02 10:32:38 +01:00
Mark Andrews
84f955a972 ISC_RUN_TEST_IMPL should use a static declaration
These functions don't need to be called from multiple places and
by making them static we will detect when they are not added to the
list functions to be tested.

(cherry picked from commit 22d664aa15)
2026-01-29 00:26:35 +11:00
Mark Andrews
016baaa06c Fix brid and hhit unit tests
These tests were not being run.

(cherry picked from commit 97af8fc519)
2026-01-27 05:46:17 +00:00
Mark Andrews
1c32c8dba2 Fix and call tsig_badsig unit test
(cherry picked from commit 8da2310511)
2026-01-24 07:29:59 +11:00
Mark Andrews
5b4e36fbfc Fix dsync unit test
The dsync unit test was not being run and the domain names in
the test data should have been fully qualified.

(cherry picked from commit 2159f74a1f)
2026-01-23 14:24:27 +00:00
Nicki Křížek
0a09df0b7a Support compilation with cmocka 2.0.0+
The `assert_in_range()` function was deprecated in favor of
`assert_int_in_range()` and `assert_uint_in_range()`. Add compatibility
shims for cmocka<2.0.0 and use the new functions.

(cherry picked from commit 6843a4bd9a)
2026-01-07 11:17:42 +01:00
Matthijs Mekking
63262fd0f4 Implement dns_dbiterator_seek3
This is a new seek function for dbiterator that is meant to find an
NSEC3 node in a zone database. The difference with dns_dbiterator_seek
is that if the node does not exist, this seek function will point the
iterator to the next NSEC3 name.

(cherry picked from commit 41159e9062)
2025-12-11 13:53:25 +01:00
Evan Hunt
25c9fb54da standardize CHECK and RETERR macros
previously, there were over 40 separate definitions of CHECK macros, of
which most used "goto cleanup", and the rest "goto failure" or "goto
out". there were another 10 definitions of RETERR, of which most were
identical to CHECK, but some simply returned a result code instead of
jumping to a cleanup label.

this has now been standardized throughout the code base: RETERR is for
returning an error code in the case of an error, and CHECK is for jumping
to a cleanup tag, which is now always called "cleanup". both macros are
defined in isc/util.h.

(cherry picked from commit 52bba5cc34)
2025-12-03 19:17:20 -08:00
Mark Andrews
b6d9d4f7a6 AMTRELAY type 0 presentation format handling was wrong
RFC 8777 specifies a placeholder value of "." for the gateway field
when the gateway type is 0 (no gateway).

(cherry picked from commit ae484d4501)
2025-11-20 08:47:22 +00:00
Ondřej Surý
2c2cb31394
Drop the unit test for testing randomness
Since we are using system routines for randomness, there's no point
in spending time and run the statistical suite for testing PRNG.

(cherry picked from commit 90b3def5e9)
2025-11-04 20:51:22 +01:00
Michał Kępień
b35d6513d8 Merge tag 'v9.20.15' into bind-9.20 2025-10-22 16:16:59 +00:00
Aram Sargsyan
3a1922f464 Fix dnssec-keygen key collision checking for KEY rrtype keys
When generating a new key, dnssec-keygen checks for possible
key ID collisions with existing keys. The dnssec.c:findmatchingkeys()
function, which is supposed to get the list of the existing keys,
fails to do that for the existing KEY rrtype keys (i.e. generated
using 'dnssec-keygen -T KEY') because it doesn't pass down to the
dst_key_fromnamedfile() -> dst_key_read_public() functions the type
of the keys it's interested in. Fix the issue by introducing a new
function parameter which tells in which type of keys the caller is
currently interested in.

(cherry picked from commit 49b7ce9a54)
2025-10-22 12:55:41 +11:00
Michal Nowak
bc35b646b9
Use clang-format-21 to update formatting 2025-10-21 12:12:01 +02:00
Ondřej Surý
2924910eee
Use cryptographically-secure pseudo-random generator everywhere
It was discovered in an upcoming academic paper that a xoshiro128**
internal state can be recovered by an external 3rd party allowing to
predict UDP ports and DNS IDs in the outgoing queries.  This could lead
to an attacker spoofing the DNS answers with great efficiency and
poisoning the DNS cache.

Change the internal random generator to system CSPRNG with buffering to
avoid excessive syscalls.

Thanks Omer Ben Simhon and Amit Klein of Hebrew University of Jerusalem
for responsibly reporting this to us.  Very cool research!

(cherry picked from commit cffcab9d5f)
2025-10-02 13:49:33 +02:00
Ondřej Surý
f65c7b0c02
Fix dns_qpmulti_memusage() on empty dns_qpmulti_t instance
The dns_qpmulti_memusage() causes assertion failure when called on
freshly created qpmulti instance because the qp->usage hasn't been
allocated yet.

(cherry picked from commit b2f653b332)
2025-09-17 14:01:44 +02:00
Mark Andrews
c0b39b9093 Add tests for BRID and HHIT
(cherry picked from commit 92621e6390)
2025-09-03 11:02:15 +10:00
Mark Andrews
ae6704b4fb Add tests for DSYNC
(cherry picked from commit 53c8c5233a)
2025-08-06 13:47:33 +10:00
Michal Nowak
cb96d9c8e2 Import isc/list.h after cmocka to avoid redefinition errors
In file included from diff_test.c:25:
    /usr/local/include/cmocka.h:2333:1: error: unknown attribute '_Noreturn' ignored [-Werror,-Wunknown-attributes]
     2333 | CMOCKA_NORETURN void _fail(const char * const file, const int line);
          | ^~~~~~~~~~~~~~~
    /usr/local/include/cmocka.h:129:41: note: expanded from macro 'CMOCKA_NORETURN'
      129 | #define CMOCKA_NORETURN __attribute__ ((noreturn))
          |                                         ^~~~~~~~
    /usr/include/stdnoreturn.h:36:19: note: expanded from macro 'noreturn'
       36 | #define noreturn                _Noreturn
          |                                 ^~~~~~~~~
2025-07-29 14:07:05 +02:00
Ondřej Surý
485aac9213
Rename 'free' variable to 'nfree' to not clash with free()
The beauty and horrors of the C - the compiler properly detects variable
shadowing, but you can freely shadow a standard function 'free()' with
variable called 'free'.  And if you reference 'free()' just as 'free'
you get the function pointer which means you can do also pointer
arithmetics, so 'free > 0' is always valid even when you delete the
local variable.

Replace the local variables 'free' with a name that doesn't shadow the
'free()' function to prevent future hard to detect bugs.

(cherry picked from commit 855960ce46)
2025-07-22 14:28:15 +02:00
Mark Andrews
53738b0e5e Use clang-format-20 to update formatting
(cherry picked from commit 422b9118e8)
2025-06-25 13:32:08 +10:00
Mark Andrews
072f5d0009 Preserve brackets around string concatenation
We need disable clang-format here to preserve the brackets around
the string concatenation to prevent -Wstring-concatenation -Werror
breaking the build.

(cherry picked from commit eeafcee7ad)
2025-06-25 13:26:13 +10:00
Mark Andrews
3b20e48658 Silence potential divide by zero warning in qpmulti.c
Coverity flagged a potential divide by zero error in collect in
qpmulti.c when the elapsed time is zero but that is only called
once the elapsed time is greater than or equal to RUNTIME (1/4
second) so INSIST this is the case.

(cherry picked from commit 081dbb1108)
2025-06-02 23:41:21 +00:00
Evan Hunt
12d13ff071
Prevent assertion when processing TSIG algorithm
In a previous change, the "algorithm" value passed to
dns_tsigkey_create() was changed from a DNS name to an integer;
the name was then chosen from a table of known algorithms. A
side effect of this change was that a query using an unknown TSIG
algorithm was no longer handled correctly, and could trigger an
assertion failure.  This has been corrected.

The dns_tsigkey struct now stores the signing algorithm
as dst_algorithm_t value 'alg' instead of as a dns_name,
but retains an 'algname' field, which is used only when the
algorithm is DST_ALG_UNKNOWN.  This allows the name of the
unrecognized algorithm name to be returned in a BADKEY
response.

(cherry picked from commit decf461d68846d6754c1f64790c3f9006d158a1d)
2025-05-07 13:45:48 +02:00
Aram Sargsyan
b959ac44a7 Fix the isc_rwlock_tryupgrade() function's unit test
The pthread-based implementation of the isc_rwlock_tryupgrade()
function always returns ISC_R_LOCKBUSY. Fix the test by adding
conditional checks.

(cherry picked from commit c27659bc62)
2025-04-16 16:04:08 +00:00
Mark Andrews
e09eb2ff21 Fix OID check for PRIVATEOID keys and signatures
We were failing to account for the length byte before the OID.
See RFC 4034.

   Algorithm number 254 is reserved for private use and will never be
   assigned to a specific algorithm.  The public key area in the DNSKEY
   RR and the signature area in the RRSIG RR begin with an unsigned
   length byte followed by a BER encoded Object Identifier (ISO OID) of
   that length.  The OID indicates the private algorithm in use, and the
   remainder of the area is whatever is required by that algorithm.
   Entities should only use OIDs they control to designate their private
   algorithms.

(cherry picked from commit ca7355b7d0)
2025-04-09 20:07:31 +00:00
Colin Vidal
30a5031c8c fix out-of-tree mem_test
Previously changed mem_test (!10320) introduces a test which checks for
the value of `__FILE__`, which is different if the build is done
out-of-tree or not, even though this is not relevant for the test (only
the base filename is). This result in a broken test for out-of-tree
builds. Fix this by changing the way the "grep" is done in the test,
ignoring the optional path prefix in the filename.

(cherry picked from commit b7ae514b3b)
2025-03-28 14:55:15 +00:00
Colin Vidal
c1352b79ca copy __FILE__ when allocating memory
When allocating memory under -m trace|record, the __FILE__ pointer is
stored, so it can be printed out later in order to figure out in which
file an allocation leaked. (among others, like the line number).

However named crashes when called with -m record and using a plugin
leaking memory. The reason is that plugins are unloaded earlier than
when the leaked allocations are dumped (obviously, as it's done as late
as possible). In such circumstances, __FILE__ is dangling because the
dynamically loaded library (the plugin) is not in memory anymore.

Fix the crash by systematically copying the __FILE__ string
instead of copying the pointer. Of course, this make each allocation to
consume a bit more memory (and longer, as it needs to calculate the
length of __FILE__) but this occurs only under -m trace|record debugging
flags.

In term of unit test, because grepping in C is not fun, and because the
whole "syntax" of the dump output is tested in other tests, this simply
search for a substring in the whole buffer to make sure the expected
allocations are found.

(cherry picked from commit 4eb2cd364a)
2025-03-27 14:21:00 +01:00
Colin Vidal
ad3e09a6af IPv6 case to isc_netaddr_masktoprefixlen tests
Unit test for isc_netaddr_masktoprefixlen were missing IPv6 mask cases.
Add those and few other IPv4 cases. Also, the test is refactored in
order to make it easy to add new cases.

(cherry picked from commit ad2c3fa4f7)
2025-03-26 13:30:46 +00:00
Mark Andrews
6d2bd55794 Silence warning when initialising compress
The string literal initialalising compressed was too big for the
array as it has an unwanted NUL terminator.  This is allowed for
in C for historical reasons but produces a warning with some
compilers.  Adjust the declaration to include the NUL and adjust
the users to pass in an adjusted size which excludes the NUL rather
than sizeof(compressed).

(cherry picked from commit 6a6b6be824)
2025-03-26 12:43:55 +00:00
Evan Hunt
dd1050e938 qpzone find() function could set foundname incorrectly
when a requested name is found in the QP trie during a lookup, but its
records have been marked as nonexistent by a previous deletion, then
it's treated as a partial match, but the foundname could be left
pointing to the original qname rather than the parent. this could
lead to an assertion failure in query_findclosestnsec3().
2025-03-17 09:27:09 +00:00
Evan Hunt
ba8d69648e add a unit test with an empty node
the db_test unit test now looks up an empty nonterminal node
to exercise the behavior of the step() function in qpzone.

(cherry picked from commit ecde0ea2d7)
2025-03-14 23:23:00 +00:00
Evan Hunt
6a9e04d46a add a unit test to check database rollback
check that a database rollback works and the correct
(original) data is found on lookup.

(cherry picked from commit 7d98aba3ac)
2025-03-14 23:23:00 +00:00
Evan Hunt
cc0fc98244 wrap ns_client_error() for unit testing
When testing, the client object doesn't have a proper
netmgr handle, so ns_client_error() needs to be a no-op.

(cherry picked from commit ae37ef45ff)
2025-02-26 00:55:51 +00:00
Mark Andrews
a0dae15cd1 Relax private DNSKEY and RRSIG constraints
DNSKEY, KEY, RRSIG and SIG constraints have been relaxed to allow
empty key and signature material after the algorithm identifier for
PRIVATEOID and PRIVATEDNS. It is arguable whether this falls within
the expected use of these types as no key material is shared and
the signatures are ineffective but these are private algorithms and
they can be totally insecure.

(cherry picked from commit b048190e23)
2025-02-25 23:40:38 +00:00
Ondřej Surý
c6c03a6b11
Reduce false sharing in dns_qpzone
Instead of having many node_lock_count * sizeof(<member>) arrays, pack
all the members into a qpzone_bucket_t that is cacheline aligned and have
a single array of those.

(cherry picked from commit 6dcc398726)
2025-02-04 23:28:50 +01:00
Ondřej Surý
7dab6cdfbc
Remove db_nodelock_t in favor of reference counted qpdb
This removes the db_nodelock_t structure and changes the node_locks
array to be composed only of isc_rwlock_t pointers.  The .reference
member has been moved to qpdb->references in addition to
common.references that's external to dns_db API users.  The .exiting
members has been completely removed as it has no use when the reference
counting is used correctly.

(cherry picked from commit 431513d8b3)
2025-01-31 05:49:36 +01:00