2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 05:57:52 +00:00

9375 Commits

Author SHA1 Message Date
Matthijs Mekking
2a4daaedca Add signatures-jitter option
Add an option to speficy signatures jitter.
2024-04-18 09:50:10 +02:00
Mark Andrews
bf70d4840c dns_qpkey_toname failed to reset name correctly
This could lead to a mismatch between name->length and the rest
of the name structure.
2024-04-18 00:17:48 +00:00
Ondřej Surý
eb1829b970
Use atomic operations to access the trust byte in ncache data
Protect the access to the trust byte in the ncache data with relaxed
atomic operation to mimick the current behaviour.  This will teach
TSAN that the concurrent access is fine.
2024-04-17 17:14:34 +02:00
Mark Andrews
4ef755ffb0
Only copy the name data after we know its actual length
This prevents TSAN errors with the ncache code where the trust byte
access needs to be protected by a lock.  The old code copied the
entire region before determining where the name ended.  We now
determine where the name ends then copy just that data and in doing
so avoid reading the trust byte.
2024-04-17 17:14:34 +02:00
Mark Andrews
40fd4cd407 Wrong source address used for IPv6 notify messages
The source address field of 'newnotify' was not updated from the
default (0.0.0.0) when the destination address was an IPv6 address.
This resulted in the messages failing to be sent.  Set the source
address to :: when the destination address is an IPv6 address.
2024-04-11 18:05:25 +00:00
Evan Hunt
2c88946590 dns_name_dupwithoffsets() cannot fail
this function now always returns success; change it to void and
clean up its callers.
2024-04-10 22:51:07 -04:00
Aram Sargsyan
a5ea7bcd25
Rename and fix dns_validator_destroy() to dns_validator_shutdown()
Since the dns_validator_destroy() function doesn't guarantee that
it destroys the validator, rename it to dns_validator_shutdown()
and require explicit dns_validator_detach() to follow.

Enforce the documented function requirement that the validator must
be completed when the function is called.

Make sure to set val->name to NULL when the function is called,
so that the owner of the validator may destroy the name, even if
the validator is not destroyed immediately. This should be safe,
because the name can be used further only for logging by the
offloaded work callbacks when they detect that the validator is
already canceled/complete, and the logging function has a condition
to use the name only when it is non-NULL.
2024-04-02 16:21:54 +02:00
Aram Sargsyan
a6c6ad048d Remove a redundant log message and a comment
If val->result is not ISC_R_SUCCESS, a similar message is logged
further down in the function. Remove the redundant log message.

Also remove an unnecessary code comment line.
2024-04-02 10:34:31 +00:00
Evan Hunt
63659e2e3a
complete removal of isc_loop_current()
isc_loop() can now take its place.

This also requires changes to the test harness - instead of running the
setup and teardown outside of th main loop, we now schedule the setup
and teardown to run on the loop (via isc_loop_setup() and
isc_loop_teardown()) - this is needed because the new the isc_loop()
call has to be run on the active event loop, but previously the
isc_loop_current() (and the variants like isc_loop_main()) would work
even outside of the loop because it needed just isc_tid() to work, but
not the full loop (which was mainly true for the main thread).
2024-04-02 10:35:56 +02:00
Evan Hunt
c47fa689d4
use a thread-local variable to get the current running loop
if we had a method to get the running loop, similar to how
isc_tid() gets the current thread ID, we can simplify loop
and loopmgr initialization.

remove most uses of isc_loop_current() in favor of isc_loop().
in some places where that was the only reason to pass loopmgr,
remove loopmgr from the function parameters.
2024-04-02 10:35:56 +02:00
Evan Hunt
ea6659a5e9
update foundname when detecting a zonecut above qname
an assertion could be triggered in the QPDB cache if a DNAME
was found above a queried NS, because the 'foundname' value was
not correctly updated to point to the zone cut.

the same mistake existed in qpzone and has been fixed there as well.
2024-04-02 10:00:03 +02:00
Matthijs Mekking
77d4bb9751 Fix fix_iterator hang
If there are no more previous leaves, it means the queried name
precedes the entire range of names in the database, so we should just
move the iterator one step back and return, instead of continuing our
search for the predecessor.

This is similar to an earlier bug fixed in an earlier commit:

    ea9a8cb392ff59438a911485742b220d40f24d6f
2024-03-25 10:40:23 +01:00
Mark Andrews
4d2d80f534 Remove remenants of cache support from qpzone.c
These where leading to Coverity errors being reported.
2024-03-19 22:04:10 +00:00
Evan Hunt
17186e06bb reduce memory consumption of the remaining QP databases
use dynamically allocated names instead of fixednames in
forward.c, keytable.c, nametree.c, and nta.c
2024-03-14 10:25:07 -07:00
Evan Hunt
c0fcc2899e reduce memory consumption of rpz summary database
use dynamically allocated names instead of fixednames in rpz.c
2024-03-14 10:20:52 -07:00
Evan Hunt
8b67476249 reduce memory consumption of qpcache database
as with qpzone, use a dynamically-allocated dns_name instead
of a dns_fixedname object to store node names in the QP database.
2024-03-14 10:20:52 -07:00
Evan Hunt
f908d358c4 reduce memory consumption of qpzone database
every node of a QP database contains a copy of the nodename,
which is used as the key for the QP-trie. previously, the name
was stored as a dns_fixedname object, which has room for up to
255 characters. we can reduce the space consumed by dynamically
allocating a dns_name object that's just long enough for the name
to be stored.
2024-03-14 10:20:52 -07:00
Matthijs Mekking
ad33a73f83 Fix Coverity CID 487882: Error handling issues
The dns_qpiter_next() was called without checking the return value. If
we cannot move the iterator forward, there is no use in calling the
step() function.

/lib/dns/qpzone.c: 2804 in activeempty()
2798     	 * of the name we were searching for. Step the iterator
2799     	 * forward, then step() will continue forward until it
2800     	 * finds a node with active data. If that node is a
2801     	 * subdomain of the one we were looking for, then we're
2802     	 * at an active empty nonterminal node.
2803     	 */
>>>     CID 487882:  Error handling issues  (CHECKED_RETURN)
>>>     Calling "dns_qpiter_next" without checking return value (as is done elsewhere 26 out of 27 times).
2804     	dns_qpiter_next(it, NULL, NULL, NULL);
2805     	return (step(search, it, FORWARD, next) &&
2806     		dns_name_issubdomain(next, current));
2807     }
2024-03-14 14:01:23 +01:00
Matthijs Mekking
659fa0cbc3 Fix Coverity CID 487884: Dead code in qpcache.c
Adding a changed record is zonedb related and does not belong in
the cache code. This is a leftover dead code and can be safely
removed.

/lib/dns/qpcache.c: 3459 in add()
3453     			}
3454     			newheader->next = topheader->next;
3455     			newheader->down = topheader;
3456     			topheader->next = newheader;
3457     			qpnode->dirty = 1;
3458     			if (changed != NULL) {
>>>     CID 487884:    (DEADCODE)
>>>     Execution cannot reach this statement: "changed->dirty = true;".
3459     				changed->dirty = true;
3460     			}
3461     		} else {
3462     			/*
3463     			 * No rdatasets of the given type exist at the node.
3464     			 */
/lib/dns/qpcache.c: 3409 in add()
3403     			}
3404     			newheader->next = topheader->next;
3405     			newheader->down = topheader;
3406     			topheader->next = newheader;
3407     			qpnode->dirty = 1;
3408     			if (changed != NULL) {
>>>     CID 487884:    (DEADCODE)
>>>     Execution cannot reach this statement: "changed->dirty = true;".
3409     				changed->dirty = true;
3410     			}
3411     			mark_ancient(header);
3412     			if (sigheader != NULL) {
3413     				mark_ancient(sigheader);
3414
2024-03-14 10:42:30 +00:00
Evan Hunt
b3c8b5cfb2 remove dead code in rbtdb.c
dns_db_addrdataset() enforces a requirement that version can only
be NULL for a cache database. code that checks for zone semantics
and version == NULL can never be reached.
2024-03-13 17:15:18 -07:00
Evan Hunt
29f1c93734 support nodefullname in rbt-zonedb.c
this enables the 'dyndb' system test to pass when we
build using --with-zonedb=rbt.
2024-03-13 17:15:18 -07:00
Evan Hunt
f0b164430a remove dead code in qpzone.c
qpzone does not support cache semantics, so dns_db_addrdataset(),
_deleterdataset() and _subtractrdataset() can't be run with
version == NULL; there's no need to check for it.

we can also clean up free_qpdb() a bit since current_version
is always non-NULL.
2024-03-13 17:15:18 -07:00
Mark Andrews
228cc557fe Only call memmove if the rdata length is non zero
This avoids undefined behaviour on zero length rdata where the
data pointer is NULL.
2024-03-13 23:04:56 +00:00
Matthijs Mekking
0aac81cf80 Fix bug in keymgr Depends function
The Depends relation refers to types of rollovers in which a certain
record type is going to be swapped. Specifically, the Depends relation
says there should be no dependency on the predecessor key (the set
Dep(x, T) must be empty).

But if the key is phased out (all its states are in HIDDEN), there is
no longer a dependency. Since the relationship is still maintained
(Predecessor and Successor metadata), the keymgr_dep function still
returned true. In other words, the set Dep(x, T) is not considered
empty.

This slows down key rollovers, only retiring keys when the successor
key has been fully propagated.
2024-03-13 10:58:24 +01:00
Matthijs Mekking
fb2f0c8168 Fix validate_dnskey_dsset when KSK is not signing
When there is a secure chain of trust with a KSK that is not actively
signing the DNSKEY RRset, the code for validating the DNSKEY RRset
against the DS RRset could potentially skip DS records, thinking the
chain of trust is broken while there is a valid DS with corresponding
DNSKEY record present.

This is because we pass the result ISC_R_NOMORE on when we are done
checking for signatures, but then treat it as "no more DS records".

Chaning the return value to something else (DNS_R_NOVALIDSIG seems the
most appropriate here) fixes the issue.
2024-03-12 09:10:41 +01:00
Evan Hunt
5709f7bad9 rename qpdb to qpcache
move qpdb.c to qpcache.c and rename the "qp" database implementation
to "qpcache", in order to make it more clearly distinguishable from
"qpzone".
2024-03-08 15:36:56 -08:00
Evan Hunt
e14a116ced collapse qpdb implementation down to one file
the code in qpdb.c was previously shared by qp-cachedb.c and
qp-zonedb.c.  since qp-zonedb.c no longer exists, it's not necessary
to keep these separate any longer. the two files have been merged,
and functions that were previously globally accessible have been
changed to static and renamed.
2024-03-08 15:36:56 -08:00
Evan Hunt
ab084d8c4f remove qp-zonedb.c and associated code
now that "qpzone" databases are available for use in zones, we no
longer need to retain the zone semantics in the "qp" database.

all zone-specific code has been removed from QPDB, and "configure
--with-zonedb" once again takes two values, rbt and qp.

some database API methods that are never used with a cache have
been removed from qpdb.c and qp-cachedb.c; these include newversion,
closeversion, subtractrdataset, and nodefullname.
2024-03-08 15:36:56 -08:00
Evan Hunt
ac2c454f4f add a nodefullname implementation for the qpzone database
this enables the 'dyndb' system test to use a qpzone database.
2024-03-08 15:36:56 -08:00
Evan Hunt
3512cf5654 add setup/commit functions to rdatacallbacks
because dns_qpmulti_commit() can be time consuming, it's inefficient
to open and commit a qpmulti transaction for each rdataset being loaded
into a database.  we can improve load time by opening a qpmulti
transaction before adding a group of rdatasets and then committing it
afterward.

this commit adds 'setup' and 'commit' functions to dns_rdatacallbacks_t,
which can be called before and after the loops in which 'add' is
called in dns_master_load() and axfr_apply().
2024-03-08 15:36:56 -08:00
Evan Hunt
2e45866715 use DNS_DB_NONSEC3 flag when copying non-dnssec records
when copying the non-dnssec records in receive_secure_db(),
use DNS_DB_NONSEC3 so we don't accidentally create nodes in
the main tree for NSEC3 records. this was a long-standing error
in the code, but was harmless in the RBTDB.
2024-03-08 15:36:56 -08:00
Evan Hunt
55f38e34dc improve node reference counting
QP database node data is not reference counted the same way RBT nodes
were: in the RBT, node->references could be zero if the node was in the
tree but was not in use by any caller, whereas in the QP trie, the
database itself uses reference counting of nodes internally.

this caused some subtle errors. in RBTDB, when the newref() function is
called and the node reference count was zero, the node lock reference
counter would also be incremented. in the QP trie, this can never
happen - because as long as the node is in the database its reference
count cannot be zero - and so the node lock reference counter was never
incremented.

this has been addressed by maintaining a separate "erefs" counter for
external references to the node. this is the same approach used in the
"qpdb-lite" database in commit e91fbd8dea.

while troubleshooting this issue, some compile errors were discovered
when building with DNS_DB_NODETRACE; those have also been fixed.
2024-03-08 15:36:56 -08:00
Evan Hunt
2b4133a32c switch default zone database from "qp" to "qpzone"
use the dns_qpmulti-based "qpzone" by default throughout BIND,
instead of the existing dns_qp-based "qp", when creating zone
databases. (cache databases still use "qp".)

the "--with-zonedb" option has been updated in configure.ac to permit
the use of both "qp" and "qpzone" databases.

in zone.c there was a test that prevented any database type other than
"qp" from hosting an RPZ. this was outdated, and has been removed.
2024-03-08 15:36:56 -08:00
Evan Hunt
2222728a4f release RCU in dns_qpmulti_snapshot()
previously, an RCU critical section was held open for the duration
of a snapshot. this should not be necessary, as the snapshot makes
local copies of QP trie metadata, and it causes problems when a
DB iterator is held open between two loop events.  we now call
rcu_read_unlock() after setting up the snapshot.
2024-03-08 15:36:56 -08:00
Evan Hunt
6e167724e7 complete the qpzone database API implementation
finish importing the database API methods from RBTDB to qpzone:
issecure, nodecount, getnsec3parameters, findnsec3node, setsigningtime,
getsigningtime, getsize, setgluecachestats, locknode, unlocknode, and
addglue.
2024-03-08 15:36:56 -08:00
Evan Hunt
f46455cfcb allow updating of records in a qpzone database
add database API methods needed to apply updates to an existing zone
database (newversion, addrdataset, subtractrdataset and deleterdataset).

it is now possible to apply journals to zone databases after loading, so
named-checkzone -J works correctly.
2024-03-08 15:36:56 -08:00
Evan Hunt
60b5422cda make the qpzone database dumpable
add database API method implementations needed to iterate and dump
a qpzone database to a file (createiterator, allrdatasets and
attachversion, plus dbiterator and rdatasetiter methods).

named-checkzone -D can now dump the contents of most zones,
but zone cuts are not correctly detected.
2024-03-08 15:36:56 -08:00
Evan Hunt
628fa8a3d6 make the qpzone database loadable
add database API methods needed for loading rdatasets into memory
(currentversion, beginload, endload), plus the methods used by
zone_postload() for zone consistency checks (getoriginnode, find,
findnode, findrdataset, attachnode, detachnode, deletedata).

the QP trie doesn't support the find callback mechanism available
in dns_rbt_findnode() which allows examination of intermediate nodes
while searching, so the detection of wildcard and delegation nodes
is now done by scanning QP chains after calling dns_qp_lookup().

Note that the lookup in previous_closest_nsec() cannot return
ISC_R_NOTFOUND. In RBTDB, we checked for this return value and
ovewrote the result with ISC_R_NOMORE if it occurred. In the
qpzone implementation, we insist that this return value cannot happen.
dns_qp_lookup() would only return ISC_R_NOTFOUND if we asked for a
name outside the zone's authoritative domain, and we never do that
when looking up a predecessor NSEC record.

named-checkzone is now able to load a zone and check it for errors,
but cannot dump it.
2024-03-08 15:36:49 -08:00
Evan Hunt
be24feb252 stub dns_qpmulti-based zone database implementation
created files for a dns_qpmulti-based zone database, "qpzone".
currently this only has create and destroy functions.
2024-03-06 20:57:31 -08:00
Mark Andrews
926d2e4cf2 dns_db_setloop called at wrong place on wrong db
In cache_create_db, dns_db_setloop should be called on the newly
created db only if the database creation succeeded.
2024-03-07 13:10:23 +11:00
Ondřej Surý
d492d676ef
Move the dns_db_setloop into cache_create_db()
The dns_cache_flush() drops the old database and creates a new one, but
it forgets to pass the loop that runs the node pruning and cleaning
the rbtdb when flushing it next time.  This causes the cleaning to skip
cleaning the parent nodes (with .down == NULL) leading to increased
memory usage over time until the database is unable to keep up and just
stays overmem all the time.
2024-03-06 18:33:33 +01:00
Ondřej Surý
454c75a33a
Restore the parent cleaning logic in prune_tree()
Reconstruct the variant of the prune_tree() parent cleaning to consider
all elibible parents in a single loop as we were doing before all the
changes that led to this commit.

Update code comments so that they more precisely describe what the
relevant bits of code actually do.
2024-03-06 13:03:17 +01:00
Evan Hunt
92b305be4b add a compile-time option to select default zone and cache DB
by default, QPDB is the database used by named and all tools and
unit tests. the old default of RBTDB can now be restored by using
"configure --with-zonedb=rbt --with-cachedb=rbt".

some tests have been fixed so they will work correctly with either
database.

CHANGES and release notes have been updated to reflect this change.
2024-03-06 10:49:02 +01:00
Matthijs Mekking
3facc5b51d Fix race condition crash
When running resolver benchmark pipeline, a crash occurred:

https://gitlab.isc.org/isc-projects/bind9-shotgun-ci/-/pipelines/163946

In the code we are doing a lookup, it fails (meaning there is no node
with lookup name), we create the node and insert it and it fails.
But dns_qp_insert can only return ISC_R_SUCCESS or ISC_R_EXISTS.
So it must have been inserted in between. This is a race condition bug.

The first lookup only requires a write lock and if the lookup failed
the lock gets upgraded to a write lock and we insert the missing data.

To fix the race condition bug, we need to do a lookup again after we
have upgraded the lock to make sure it wasn't inserted in the mean
time.
2024-03-06 10:49:02 +01:00
Matthijs Mekking
7db974b240 Remove pruning tree code
Since qp-tries does not store interior nodes, we can remove all code
related to pruning the tree.
2024-03-06 10:49:02 +01:00
Matthijs Mekking
78fd4e2b5c Update qpdb.c to make coccinelle happy
Applying semantic patch cocci/isc_mem_cget.spatch...
150 files match
diff -u -p a/lib/dns/qpdb.c b/lib/dns/qpdb.c
--- a/lib/dns/qpdb.c
+++ b/lib/dns/qpdb.c
@@ -3801,16 +3801,15 @@ dns__qpdb_create(isc_mem_t *mctx, const
		goto cleanup_tree_lock;
	}
	INSIST(qpdb->node_lock_count < (1 << DNS_RBT_LOCKLENGTH));
-	qpdb->node_locks = isc_mem_get(mctx, qpdb->node_lock_count *
-						      sizeof(db_nodelock_t));
+	qpdb->node_locks = isc_mem_cget(mctx, qpdb->node_lock_count,
+					 sizeof(db_nodelock_t));

	qpdb->common.update_listeners = cds_lfht_new(16, 16, 0, 0, NULL);

	if (IS_CACHE(qpdb)) {
		dns_rdatasetstats_create(mctx, &qpdb->rrsetstats);
-		qpdb->lru = isc_mem_get(mctx,
-					 qpdb->node_lock_count *
-						 sizeof(dns_slabheaderlist_t));
+		qpdb->lru = isc_mem_cget(mctx, qpdb->node_lock_count,
+					  sizeof(dns_slabheaderlist_t));
		for (i = 0; i < (int)qpdb->node_lock_count; i++) {
			ISC_LIST_INIT(qpdb->lru[i]);
		}
@@ -3819,8 +3818,8 @@ dns__qpdb_create(isc_mem_t *mctx, const
	/*
	 * Create the heaps.
	 */
-	qpdb->heaps = isc_mem_get(hmctx, qpdb->node_lock_count *
-						  sizeof(isc_heap_t *));
+	qpdb->heaps = isc_mem_cget(hmctx, qpdb->node_lock_count,
+				    sizeof(isc_heap_t *));
	for (i = 0; i < (int)qpdb->node_lock_count; i++) {
		qpdb->heaps[i] = NULL;
	}
@@ -3834,8 +3833,8 @@ dns__qpdb_create(isc_mem_t *mctx, const
	/*
	 * Create deadnode lists.
	 */
-	qpdb->deadnodes = isc_mem_get(mctx, qpdb->node_lock_count *
-						     sizeof(dns_qpdatalist_t));
+	qpdb->deadnodes = isc_mem_cget(mctx, qpdb->node_lock_count,
+					sizeof(dns_qpdatalist_t));
	for (i = 0; i < (int)qpdb->node_lock_count; i++) {
		ISC_LIST_INIT(qpdb->deadnodes[i]);
	}
2024-03-06 10:49:02 +01:00
Evan Hunt
89c4c1aa87 add dns_db_nodefullname()
the dyndb test requires a mechanism to retrieve the name associated
with a database node, and since the database no longer uses RBT for
its underlying storage, dns_rbt_fullnamefromnode() doesn't work.
addressed this by adding dns_db_nodefullname() to the database API.
2024-03-06 10:49:02 +01:00
Matthijs Mekking
cdf62a18e7 Rework dbiterator implementation
If the iterator is paused, the tree is unlocked and may change.

In an RBT tree it's always possible to resume iteration as long
as a valid node pointer was still held, but now that the underlying
database structure is a QP trie, the iterator needs to be initialized
based on the existing structure of the trie or it will return
inconsistent results. We now call dns_qp_lookup() to reinitialize
the QP iterator whenever dbiterator_next() or dbiterator_prev() is
called on a paused iterator.
2024-03-06 10:49:02 +01:00
Matthijs Mekking
e91fbd8dea Improve node reference counting
QP database node data is not reference counted the same way RBT nodes
were: in the RBT, node->references could be zero if the node was in the
tree but was not in use by any caller, whereas in the QP trie, the
database itself uses reference counting of nodes internally.

this caused some subtle errors. in RBTDB, when the newref() function is
called and the node reference count was zero, the node lock reference
counter would also be incremented. in the QP trie, this can never
happen - because as long as the node is in the database its reference
count cannot be zero - and so the node lock reference counter was never
incremented.

reference counting will probably need to be refactored in more detail
later; the node lock reference count may not be needed at all.  but
for now, as a temporary measure, we add a third reference counter,
'erefs' (external references), to the dns_qpdata structure. this is
counted separately from the main reference counter, and should match
the node reference count as it would have been in RBTDB.

this change revealed a number of places where the node reference counter
was being incremented on behalf of a caller without newref() being
called; those were cleaned up as well.

This is an adaptation of commit 3dd686261d2c4bcd15a96ebfea10baffa277732b
2024-03-06 10:49:02 +01:00
Matthijs Mekking
91a2755433 No special logic for relative names
Nodes in a QP-trie contain the full domain name, while nodes in a
red-black tree only contain names relative to a parent.
2024-03-06 10:49:02 +01:00