Commit Graph

14326 Commits

Author SHA1 Message Date
Ondřej Surý
2ddea1e41c Add a static pre-allocated buffer to isc_buffer_t
When the buffer is allocated via isc_buffer_allocate() and the size is
smaller or equal ISC_BUFFER_STATIC_SIZE (currently 512 bytes), the
buffer will be allocated as a flexible array member in the buffer
structure itself instead of allocating it on the heap.  This should help
when the buffer is used on the hot-path with small allocations.
2022-12-20 19:13:48 +01:00
Ondřej Surý
6bd2b34180 Enable auto-reallocation for all isc_buffer_allocate() buffers
When isc_buffer_t buffer is created with isc_buffer_allocate() assume
that we want it to always auto-reallocate instead of having an extra
call to enable auto-reallocation.
2022-12-20 19:13:48 +01:00
Ondřej Surý
135ec7a0f0 Remove single use isc_buffer_putdecint() function
The isc_buffer_putdecint() could be easily replaced with
isc_buffer_printf() with just a small overhead of calling vsnprintf()
twice instead once.  This is not on a hot-path (dns_catz unit), so we
can ignore the overhead and instead have less single-use code in favor
of using reusable more generic function.
2022-12-20 19:13:48 +01:00
Ondřej Surý
2a94123d5b Refactor the isc_buffer_{get,put}uintN, add isc_buffer_peekuintN
The Stream DNS implementation needs a peek methods that read the value
from the buffer, but it doesn't advance the current position.  Add
isc_buffer_peekuintX methods, refactor the isc_buffer_{get,put}uintN
methods to modern integer types, and move the isc_buffer_getuintN to the
header as static inline functions.
2022-12-20 19:13:48 +01:00
Ondřej Surý
a1d45685e6 Move and extend the uint8_t low-endian to uint{32,64}t to endian.h
Move the U8TO{32,64}_LE and U{32,64}TO8_LE macros to endian.h and extend
the macros for 16-bit and Big-Endian variants.

Use the macros both in isc_siphash (LE) and isc_buffer (BE) units.
2022-12-20 19:13:48 +01:00
Ondřej Surý
aea251f3bc Change the isc_buffer_reserve() to take just buffer pointer
The isc_buffer_reserve() would be passed a reference to the buffer
pointer, which was unnecessary as the pointer would never be changed
in the current implementation.  Remove the extra dereference.
2022-12-20 19:13:48 +01:00
Ondřej Surý
6f317f27ea Fix the thread safety in the dns_dispatch unit
The dispatches are not thread-bound, and used freely between various
threads (see the dns_resolver and dns_request units for details).

This refactoring make sure that all non-const dns_dispatch_t and
dns_dispentry_t members are accessed under a lock, and both object now
track their internal state (NONE, CONNECTING, CONNECTED, CANCELED)
instead of guessing the state from the state of various struct members.

During the refactoring, the artificial limit DNS_DISPATCH_SOCKSQUOTA on
UDP sockets per dispatch was removed as the limiting needs to happen and
happens on in dns_resolver and limiting the number of UDP sockets
artificially in dispatch could lead to unpredictable behaviour in case
one dispatch has the limit exhausted by others are idle.

The TCP artificial limit of DNS_DISPATCH_MAXREQUESTS makes even less
sense as the TCP connections are only reused in the dns_request API
that's not a heavy user of the outgoing connections.

As a side note, the fact that UDP and TCP dispatch pretends to be same
thing, but in fact the connected UDP is handled from dns_dispentry_t and
dns_dispatch_t acts as a broker, but connected TCP is handled from
dns_dispatch_t and dns_dispatchmgr_t acts as a broker doesn't really
help the clarity of this unit.

This refactoring kept to API almost same - only dns_dispatch_cancel()
and dns_dispatch_done() were merged into dns_dispatch_done() as we need
to cancel active netmgr handles in any case to not leave dangling
connections around.  The functions handling UDP and TCP have been mostly
split to their matching counterparts and the dns_dispatch_<function>
functions are now thing wrappers that call <udp|tcp>_dispatch_<function>
based on the socket type.

More debugging-level logging was added to the unit to accomodate for
this fact.
2022-12-19 11:42:13 +01:00
Ondřej Surý
32ff134eeb Fix reference counting in get_attached_entry (again)
When get_attached_entry() encounters entry that would be expired, it
needs to get reference to the entry before calling maybe_expire_entry(),
so the ADB entry doesn't get destroyed inside the its own lock.

This creeped into the code base again during review, so I am adding
an extra comment to prevent this.
2022-12-16 21:48:43 +01:00
Ondřej Surý
0b661b6f95 Don't expire fresh ADB names and entries
The overmem cleaning in ADB could become overzealous and clean fresh ADB
names and entries.  Add a safety check to not clean any ADB names and
entries that are below ADB_CACHE_MINIMUM threshold.
2022-12-15 16:15:19 +01:00
Ondřej Surý
59dee0b078 Exclude the ADB hashmaps from ADB overmem accounting
The ADB overmem accounting would include the memory used by hashtables
thus vastly reducing the space that can be used for ADB names and
entries when the hashtables would grow.  Create own memory context for
the ADB names and entries hash tables.
2022-12-15 16:14:16 +01:00
Ondřej Surý
a27ea1bba0 Lock the adbname and adbentry prior to unlocking hash locks
There was a datarace that could expire a freshly created ADB names and
entries between the return from get_attached_{name,entry} and locking it
again.  Lock the ADB name and ADB entry inside the hash table lock, so
they won't get expired until the full initialization has been complete.
2022-12-15 15:19:22 +01:00
Aram Sargsyan
72b1760ea6 Fix logging a uint32_t SOA serial value in dns_catz_update_from_db()
The dns_catz_update_from_db() function prints serial number as a signed
number (with "%d" in the format string), but the `vers` variable's type
is 'uint32_t'. This breaks serials bigger than 2^31.

Use PRIu32 instead of "d" in the format string.
2022-12-15 13:24:58 +00:00
Aram Sargsyan
03442d922b Clean up and refactor dns_adb_getcookie()
The dns_adb_getcookie() doesn't use the 'adb' parameter, remove it.

Refactor the dns_adb_getcookie() function to just return the size of
the cookie when the caller passes 'NULL' as the 'cookie' argument.
2022-12-15 12:34:26 +00:00
Ondřej Surý
578de673b1 Replace zonemgr_keymgmt own hash table with isc_hashmap
Instead of maintaining own hashtable implementation for zonemgr_keymgmt,
use isc_hashmap that already can resize (grow and shrink).
2022-12-14 19:37:07 +01:00
Ondřej Surý
52307f8116 Add internal logging functions to the netmgr
Add internal logging functions isc__netmgr_log, isc__nmsocket_log(), and
isc__nmhandle_log() that can be used to add logging messages to the
netmgr, and change all direct use of isc_log_write() to use those
logging functions to properly prefix them with netmgr, nmsocket and
nmsocket+nmhandle.
2022-12-14 19:34:48 +01:00
Ondřej Surý
b8c7dc2dc2 Expire names in shutdown_names() under the lock
Since there could be fetches running, we need to run expire_name() under
the lock when shutting down the names.
2022-12-14 18:49:18 +01:00
Ondřej Surý
5466a48fc9 Try next server on resolver timeout
Instead of resending to the same server on the (dispatch) timeout in the
resolver, try the next server.
2022-12-14 18:49:18 +01:00
Ondřej Surý
7cefcb6184 Allow zero length keys in isc_hashmap
In case, we are trying to hash the empty key into the hashmap, the key
is going to have zero length.  This might happen in the unit test.
Allow this and add a unit test to ensure the empty zero-length key
doesn't hash to slot 0 as SipHash 2-4 (our hash function of choice) has
no problem with zero-length inputs.
2022-12-14 17:59:07 +01:00
Artem Boldariev
837fef78b1 Fix TLS session resumption via IDs when Mutual TLS is used
This commit fixes TLS session resumption via session IDs when
client certificates are used. To do so it makes sure that session ID
contexts are set within server TLS contexts. See OpenSSL documentation
for 'SSL_CTX_set_session_id_context()', the "Warnings" section.
2022-12-14 18:06:20 +02:00
Ondřej Surý
7292ee6d92 Fix intermittent memory leak in dns_resolver unit
A rdataset could have been left unassociated on the error path in the
resume_dslookup() in the dns_resolver unit.  Clone the rdataset after
the error check, so it's not cloned before we check whether we can make
further progress chasing DS records.
2022-12-14 10:48:06 +01:00
Tony Finch
c18a9a208d Fix a typo RSASHA236 -> RSASHA256
Use dns_secalg_format() to avoid error-prone repetition.
2022-12-13 16:58:02 +00:00
Ondřej Surý
79115a0c3b Implement proper reference counting for dns_keyfileio_t
Instead of relying on hash table search when using the keys, implement a
proper reference counting in dns_keyfileio_t objects, and attach/detach
the objects to the zone.
2022-12-09 14:27:44 +01:00
Tom Krizek
ba1607747c Revert "Merge branch '3678-serve-stale-servfailing-unexpectedly' into 'main'"
This reverts commit 629f66ea8e, reversing
changes made to 84a7be327e.

It also removes release note 6038, since the fix is reverted.
2022-12-08 10:30:44 +01:00
Ondřej Surý
fb1acd6736 Release unused key file IO lock objects
Due to off-by-one error in zonemgr_keymgmt_delete, unused key file IO
lock objects were never freed and they were kept until the server
shutdown.  Adjust the returned value by -1 to accomodate the fact that
the atomic_fetch_*() functions return the value before the operation and
not current value after the operation.
2022-12-08 08:30:30 +01:00
Mark Andrews
1a39328feb Remove different zero TTL handling for rdataset iterator
Zero TTL handling does not need to be different for 'rdatasetiter_first'
and 'rdatasetiter_next' and it interacts badly with 'bind_rdatadataset'
which makes different determinations.
2022-12-07 22:20:02 +00:00
Mark Andrews
85048ddeee Add dns_db_allrdatasets options
'DNS_DB_STALEOK' returns stale rdatasets as well as current rdatasets.

'DNS_DB_EXPIREDOK' returns expired rdatasets as well as current
rdatasets. This option is currently only set when DNS_DB_STALEOK is
also set.
2022-12-07 22:20:02 +00:00
Mark Andrews
7695c36a5d Extend dns_db_allrdatasets to control interation results
Add an options parameter to control what rdatasets are returned when
iteratating over the node.  Specific modes will be added later.
2022-12-07 22:20:02 +00:00
Mark Andrews
3bdab2d111 Properly select active rdatasets when iterating across node
Active rdatasets where not being properly selected in rdatasetiter_first
and rdatasetiter_next.
2022-12-07 22:20:02 +00:00
Mark Andrews
90249e4aa5 Revert "Fix rndc dumpdb -expired for stuck cache contents"
This reverts commit f8d866c6ef.
2022-12-07 22:20:02 +00:00
Ondřej Surý
e2262c2112 Remove isc_resource API and set limits directly in named_os unit
The only function left in the isc_resource API was setting the file
limit.  Replace the whole unit with a simple getrlimit to check the
maximum value of RLIMIT_NOFILE and set the maximum back to rlimit_cur.

This is more compatible than trying to set RLIMIT_UNLIMITED on the
RLIMIT_NOFILE as it doesn't work on Linux (see man 5 proc on
/proc/sys/fs/nr_open), neither it does on Darwin kernel (see man 2
getrlimit).

The only place where the maximum value could be raised under privileged
user would be BSDs, but the `named_os_adjustnofile()` were not called
there before.  We would apply the increased limits only on Linux and Sun
platforms.
2022-12-07 19:40:00 +01:00
Ondřej Surý
0c62c0bdb7 Mark setting operating system limits from named.conf as ancient
After deprecating the operating system limits settings (coresize,
datasize, files and stacksize), mark them as ancient and remove the code
that sets the values from config.
2022-12-07 19:40:00 +01:00
Ondřej Surý
715343c31d Remove dead code from dns_cache_flush()
After removing the cache cleaning mechanism, we don't need to db
iterator in dns_cache_flush() anymore.
2022-12-07 19:11:08 +01:00
Ondřej Surý
5111258e7a Propagate the shutdown event to the recursing ns_client(s)
Send the ns_query_cancel() on the recursing clients when we initiate the
named shutdown for faster shutdown.

When we are shutting down the resolver, we cancel all the outstanding
fetches, and the ISC_R_CANCEL events doesn't propagate to the ns_client
callback.

In the future, the better solution how to fix this would be to look at
the shutdown paths and let them all propagate from bottom (loopmgr) to
top (f.e. ns_client).
2022-12-07 18:05:36 +01:00
Ondřej Surý
c2be97eeff Fix reference counting in get_attached_entry
When get_attached_entry() encounters entry that would be expired, it
needs to get reference to the entry before calling maybe_expire_entry(),
so the ADB entry doesn't get destroyed inside the its own lock.
2022-12-07 16:16:22 +01:00
Mark Andrews
b1086a5561 Add missing DbC magic checks
Checking for value != NULL is not sufficient to detect use after
free errors.
2022-12-07 09:04:08 +11:00
Mark Andrews
35839e91d8 Call dns_db_updatenotify_unregister earlier
dns_db_updatenotify_unregister needed to be called earlier to ensure
that listener->onupdate_arg always points to a valid object.  The
existing lazy cleanup in rbtdb_free did not ensure that.
2022-12-07 09:04:08 +11:00
Mark Andrews
f13e71e551 Suppress duplicate dns_db_updatenotify_register registrations
Duplicate dns_db_updatenotify_register registrations need to be
suppressed to ensure that dns_db_updatenotify_unregister is successful.
2022-12-07 09:04:08 +11:00
Matthijs Mekking
86a80e723f Consider non-stale data when in serve-stale mode
With 'stale-answer-enable yes;' and 'stale-answer-client-timeout off;',
consider the following situation:

A CNAME record and its target record are in the cache, then the CNAME
record expires, but the target record is still valid.

When a new query for the CNAME record arrives, and the query fails,
the stale record is used, and then the query "restarts" to follow
the CNAME target. The problem is that the query's multiple stale
options (like DNS_DBFIND_STALEOK) are not reset, so 'query_lookup()'
treats the restarted query as a lookup following a failed lookup,
and returns a SERVFAIL answer when there is no stale data found in the
cache, even if there is valid non-stale data there available.

With this change, query_lookup() now considers non-stale data in the
cache in the first place, and returns it if it is available.
2022-12-06 13:26:53 +00:00
Mark Andrews
e8e40e2e01 Check that DS records are only present at delegations
This extends the integrity check to look for stray DS records
in the zone.
2022-12-06 23:27:40 +11:00
Mark Andrews
94008863de Add RUNTIME_CHECK for dns_rdata_tostruct 2022-12-04 21:41:02 +00:00
Artem Boldariev
bed5e2bb08 TLS: check for sock->recv_cb when handling received data
This commit adds a check if 'sock->recv_cb' might have been nullified
during the call to 'sock->recv_cb'. That could happen, e.g. by an
indirect call to 'isc_nmhandle_close()' from within the callback when
wrapping up.

In this case, let's close the TLS connection.
2022-12-02 13:20:37 +02:00
Artem Boldariev
8b7e123528 DoH: Avoid accessing non-atomic listener socket flags when accepting
This commit ensures that the non-atomic flags inside a DoH listener
socket object (and associated worker) are accessed when doing accept
for a connection only from within the context of the dedicated thread,
but not other worker threads.

The purpose of this commit is to avoid TSAN errors during
isc__nmsocket_closing() calls. It is a continuation of
4b5559cd8f.
2022-12-02 12:16:12 +02:00
Artem Boldariev
4d0c226375 TLS: Avoid accessing non-atomic listener socket flags during HS
This commit ensures that the non-atomic flags inside a TLS listener
socket object (and associated worker) are accessed when doing
handshake for a connection only from within the context of the
dedicated thread, but not other worker threads.

The purpose of this commit is to avoid TSAN errors during
isc__nmsocket_closing() calls. It is a continuation of
4b5559cd8f.
2022-12-02 12:16:12 +02:00
Artem Boldariev
4b5559cd8f TLS: Avoid accessing listener socket flags from other threads
This commit ensures that the flags inside a TLS listener socket
object (and associated worker) are accessed when accepting a
connection only from within the context of the dedicated thread, but
not other worker threads.
2022-12-01 21:07:49 +02:00
Ondřej Surý
e3c628d562 Honour single read per client isc_nm_read() call in the TLSDNS
The TLSDNS transport was not honouring the single read callback for
TLSDNS client.  It would call the read callbacks repeatedly in case the
single TLS read would result in multiple DNS messages in the decoded
buffer.
2022-12-01 18:31:05 +01:00
Ondřej Surý
7e4e125e5e Refactor the dns_resolver fetch context hash tables and locking
This is second in the series of fixing the usage of hashtables in the
dns_adb and the dns_resolver units.

Currently, the fetch buckets (used to hold the fetch context) and zone
buckets (used to hold per-domain counters) would never get cleaned from
the memory.  Combined with the fact that the hashtable now grows as
needed (instead of using hashtable as buckets), the memory usage in the
resolver can just grow and it never drops down.

In this commit, the usage of hashtables (hashmaps) has been completely
rewritten, so there are no "buckets" and all the matching conditions are
directly mapped into the hashtable key:

 1. For per-domain counter hashtable, this is simple as the lowercase
    domain name is used directly as a counter.

 2. For fetch context hashtable, this requires copying some extra flags
    back and forth in the key.

As we don't hold the "buckets" forever, the cleaning mechanism has been
rewritten as well:

 1. For per-domain counter hashtable, this is again much simpler, as we
    only need to check whether the usage counter is still zero under the
    lock and bail-out on cleaning if the counter is in use.

 2. For fetch context hashtable, this is more complicated as the fetch
    context cannot be reused after it has been finished.  The algorithm
    is different, the fetch context is always removed from the
    hashtable, but if we find the fetch context that has been marked
    as finished in the lookup function, we help with the cleaning from
    the hashtable and try again.

Couple of additional changes have been implemented in this refactoring
as those were needed for correct functionality and could not be split
into individual commits (or would not make sense as seperate commits):

 1. The dns_resolver_createfetch() has an option to create "unshared"
    fetch.  The "unshared" fetch will never get matched, so there's
    little point in storing the "unshared" fetch in the hashtable.
    Therefore the "unshared" fetches are now detached from the
    hashtable and live just on their own.

 2. Replace the custom reference counting with ISC_REFCOUNT_DECL/IMPL
    macros for better tracing.

 3. fctx_done_detach() is idempotent, it makes the "final" detach (the
    one matching the create function) only once.  But that also means
    that it has to be called before the detach that kept the fetch
    context alive in the callback.  A new macro fctx_done_unref() has
    been added to allow this code flow:

    fctx_done_unref(fctx, result);
    fctx_detach(&fctx);

    Doing this the other way around could cause fctx to get destroyed in
    the fctx_unref() first and fctx_done_detach() would cause UAF.

 4. The resume_qmin() and resume_dslookup() callbacks have been
    refactored for more readability and simpler code paths.  The
    validated() callback has also received some of the simplifications,
    but it should be refactored in the future as it is bit of spaghetti
    now.
2022-12-01 11:42:46 +01:00
Evan Hunt
09ee254514 change dns_db_settask() to _setloop()
The mechanism for associating a worker task to a database now
uses loops rather than tasks.

For this reason, the parameters to dns_cache_create() have been
updated to take a loop manager rather than a task manager.
2022-11-30 11:47:35 -08:00
Artem Boldariev
2bfc079946 TLS stream: always handle send callbacks asynchronously
This commit ensures that send callbacks are always called from within
the context of its worker thread even in the case of
shuttigdown/inactive socket, just like TCP transport does and with
which TLS attempts to be as compatible as possible.
2022-11-30 18:09:52 +02:00
Artem Boldariev
ef659365ce TLS Stream: use ISC_R_CANCELLED error when shutting down
This commit changes ISC_R_NOTCONNECTED error code to ISC_R_CANCELLED
when attempting to start reading data on the shutting down socket in
order to make its behaviour compatible with that of TCP and not break
the common code in the unit tests.
2022-11-30 18:09:52 +02:00
Artem Boldariev
fb9955a372 TLS Stream: fix isc_nm_read_stop() and reading flags handling
It turned out that after the latest Network Manager refactoring
'sock->reading' flag was not processed correctly. Due to this
isc_nm_read_stop() might not work as expected because reading from the
underlying TCP socket could have been resume in 'tls_do_bio()'
regardless of the 'sock->reading' value.

This bug did not seem to cause problems with DoH, so it was not
noticed, but Stream DNS has more strict expectations regarding the
underlying transport.

Additionally to the above, the 'sock->recv_read' flag was completely
ignored and corresponding logic was completely unimplemented. That did
not allow to implement one fine detail compared to TCP: once reading
is started, it could be satisfied by one datum reading.

This commit fixes the issues above.
2022-11-30 18:09:52 +02:00