2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00
Commit Graph

4757 Commits

Author SHA1 Message Date
Tony Finch
7d1ceaf35d Move per-thread RCU setup into isc_thread
All the per-loop `libuv` setup remains in `isc_loop`, but the per-thread
RCU setup is moved to `isc_thread` alongside the other per-thread setup.
This avoids repeating the per-thread setup for `call_rcu()` helpers,
and explains a little better why some parts of the per-thread setup
is missing for `call_rcu()` helpers.

This also removes the per-loop `call_rcu()` helpers as we refactored the
isc__random_initialize() in the previous commit.
2023-04-27 12:38:53 +02:00
Ondřej Surý
65021dbf52 Move the isc_random API initialization to the thread_local variable
Instead of writing complicated wrappers for every thread, move the
initialization back to isc_random unit and check whether the random seed
was initialized with a thread_local variable.

Ensure that isc_entropy_get() returns a non-zero seed.

This avoids problems with thread sanitizer tests getting stuck in an
infinite loop.
2023-04-27 12:38:53 +02:00
Tony Finch
e0248bf60f Simplify isc_thread a little
Remove the `isc_threadarg_t` and `isc_threadresult_t`
typedefs which were unhelpful disguises for `void *`,
and free the dummy jemalloc allocation sooner.
2023-04-27 12:38:53 +02:00
Tony Finch
06f534fa69 Avoid spurious compilation failures in liburcu headers
When liburcu is not installed from a system package, its headers are
not treated as system headers by the compiler, so BIND's -Werror and
other warning options take effect. The liburcu headers have a lot
of inline functions, some of which do not use all their arguments,
which BIND's build treats as an error.
2023-04-27 12:38:53 +02:00
Ondřej Surý
c2c907d728 Improve the Userspace RCU integration
This commit allows BIND 9 to be compiled with different flavours of
Userspace RCU, and improves the integration between Userspace RCU and
our event loop:

- In the RCU QSBR, the thread is put offline when polling and online
  when rcu_dereference, rcu_assign_pointer (or friends) are called.

- In other RCU modes, we check that we are not reading when reaching the
  quiescent callback in the event loop.

- We register the thread before uv_work_run() callback is called and
  after it has finished.  The rcu_(un)register_thread() has a large
  overhead, but that's fine in this case.
2023-04-27 12:38:53 +02:00
Ondřej Surý
58663574b9 Use server socket to log TCP accept failures
The accept_connection() could detach from the child socket on a failure,
so we need to keep and use the server socket for logging the accept
failures.
2023-04-27 11:07:57 +02:00
Ondřej Surý
27ad3a65f9 Fix potential UAF when shutting down isc_httpd
Use the ISC_LIST_FOREACH_SAFE() macro to safely walk the running https
and shut them down in a manner safe from deletion.
2023-04-25 08:16:46 +02:00
Ondřej Surý
ae997d9e21 Add ISC_LIST_FOREACH(_SAFE) macros
There's a recurring pattern walking the ISC_LISTs that just repeats over
and over.  Add two macros:

 * ISC_LIST_FOREACH(list, elt, link) - walk the static list
 * ISC_LIST_FOREACH_SAFE(list, elt, link, next) - walk the list in
   a manner that's safe against list member deletions
2023-04-25 08:16:46 +02:00
Evan Hunt
0393b54afb add a result code for ENOPROTOOPT, EPROTONOSUPPORT
there was no isc_result_t value for invalid protocol errors
that could be returned from libuv.
2023-04-21 12:42:10 +02:00
Ondřej Surý
b497e90179 Add isc_spinlock unit with shim pthread_spin implementation
The spinlock is small (atomic_uint_fast32_t at most), lightweight
synchronization primitive and should only be used for short-lived and
most of the time a isc_mutex should be used.

Add a isc_spinlock unit which is either (most of the time) a think
wrapper around pthread_spin API or an efficient shim implementation of
the simple spinlock.
2023-04-21 12:10:02 +02:00
Ondřej Surý
3b10814569 Fix the streaming read callback shutdown logic
When shutting down TCP sockets, the read callback calling logic was
flawed, it would call either one less callback or one extra.  Fix the
logic in the way:

1. When isc_nm_read() has been called but isc_nm_read_stop() hasn't on
   the handle, the read callback will be called with ISC_R_CANCELED to
   cancel active reading from the socket/handle.

2. When isc_nm_read() has been called and isc_nm_read_stop() has been
   called on the on the handle, the read callback will be called with
   ISC_R_SHUTTINGDOWN to signal that the dormant (not-reading) socket
   is being shut down.

3. The .reading and .recv_read flags are little bit tricky.  The
   .reading flag indicates if the outer layer is reading the data (that
   would be uv_tcp_t for TCP and isc_nmsocket_t (TCP) for TLSStream),
   the .recv_read flag indicates whether somebody is interested in the
   data read from the socket.

   Usually, you would expect that the .reading should be false when
   .recv_read is false, but it gets even more tricky with TLSStream as
   the TLS protocol might need to read from the socket even when sending
   data.

   Fix the usage of the .recv_read and .reading flags in the TLSStream
   to their true meaning - which mostly consist of using .recv_read
   everywhere and then wrapping isc_nm_read() and isc_nm_read_stop()
   with the .reading flag.

4. The TLS failed read helper has been modified to resemble the TCP code
   as much as possible, clearing and re-setting the .recv_read flag in
   the TCP timeout code has been fixed and .recv_read is now cleared
   when isc_nm_read_stop() has been called on the streaming socket.

5. The use of Network Manager in the named_controlconf, isccc_ccmsg, and
   isc_httpd units have been greatly simplified due to the improved design.

6. More unit tests for TCP and TLS testing the shutdown conditions have
   been added.

Co-authored-by: Ondřej Surý <ondrej@isc.org>
Co-authored-by: Artem Boldariev <artem@isc.org>
2023-04-20 12:58:32 +02:00
Ondřej Surý
f677cf6b73 Remove unused netmgr->worker->sendbuf
By inspecting the code, it was discovered that .sendbuf member of the
isc__nm_networker_t was unused and just consuming ~64k per worker.
Remove the member and the association allocation/deallocation.
2023-04-14 16:20:14 +02:00
Ondřej Surý
1715cad685 Refactor the isc_quota code and fix the quota in TCP accept code
In e185412872, the TCP accept quota code
became broken in a subtle way - the quota would get initialized on the
first accept for the server socket and then deleted from the server
socket, so it would never get applied again.

Properly fixing this required a bigger refactoring of the isc_quota API
code to make it much simpler.  The new code decouples the ownership of
the quota and acquiring/releasing the quota limit.

After (during) the refactoring it became more clear that we need to use
the callback from the child side of the accepted connection, and not the
server side.
2023-04-12 14:10:37 +02:00
Ondřej Surý
1768522045 Convert tls_send() callback to use isc_job_run()
The tls_send() was already using uvreq; convert this to use more direct
isc_job_run() - the on-loop no-allocation method.
2023-04-12 14:10:37 +02:00
Ondřej Surý
1302345c93 Convert isc__nm_http_send() from isc_async_run() to isc_job_run()
The isc__nm_http_send() was already using uvreq; convert this to use
more direct isc_job_run() - the on-loop no-allocation method.
2023-04-12 14:10:37 +02:00
Ondřej Surý
3adba8ce23 Use isc_job_run() for reading from StreamDNS socket
Change the reading in the StreamDNS code to use isc_job_run() instead of
using isc_async_run() for less allocations and more streamlined
execution.
2023-04-12 14:10:37 +02:00
Ondřej Surý
74cbf523b3 Run closehandle_cb on run queue instead of async queue
Instead of using isc_async_run() when closing StreamDNS handle, add
isc_job_t member to the isc_nmhandle_t structure and use isc_job_run()
to avoid allocation/deallocation on the StreamDNS hot-path.
2023-04-12 14:10:37 +02:00
Ondřej Surý
d27f6f2d68 Accept overquota TCP connection on local thread if possible
If the quota callback is called on a thread matching the socket, call
the TCP accept function directly instead of using isc_async_run() which
allocates-deallocates memory.
2023-04-12 14:10:37 +02:00
Ondřej Surý
0a468e7c9e Make isc_tid() a header-only function
The isc_tid() function is often called on the hot-path and it's the only
function is to return thread_local variable, make the isc_tid() function
a header-only to save several function calls during query-response
processing.
2023-04-12 14:10:37 +02:00
Tony Finch
3405b43fe9 Fix a division by zero bug in isc_histo
This can occur when calculating the standard deviation of an empty
histogram.
2023-04-05 23:29:21 +02:00
Mark Andrews
bf58c10dce Silence NULL pointer dereferene false positive
Only attempt to digest 'in' if it is non NULL.  This will prevent
false positives about NULL pointer dereferences against 'in' and
should also speed up the processing.
2023-04-03 13:32:40 +00:00
Artem Boldariev
2b3a3c21dc Stream DNS: avoid memory copying/buffer resizing when reading data
This commit optimises isc_dnsstream_assembler_t in such a way that
memory copying and reallocation are avoided when receiving one or more
complete DNS messages at once. We try to handle the data from the
messages directly, without storing them in an intermediate memory
buffer.
2023-04-03 13:31:46 +00:00
Tony Finch
cd0e7f853a Simplify histogram quantiles
The `isc_histosummary_t` functions were written in the early days of
`hg64` and carried over when I brought `hg64` into BIND. They were
intended to be useful for graphing cumulative frequency distributions
and the like, but in practice whatever draws charts is better off with
a raw histogram export. Especially because of the poor performance of
the old functions.

The replacement `isc_histo_quantiles()` function is intended for
providing a few quantile values in BIND's stats channel, when the user
does not want the full histogram. Unlike the old functions, the caller
provides all the query fractions up-front, so that the values can be
found in a single scan instead of a scan per value. The scan is from
larger values to smaller, since larger quantiles are usually more
interesting, so the scan can bail out early.
2023-04-03 12:08:05 +01:00
Tony Finch
bc2389b828 Add per-thread sharded histograms for heavy loads
Although an `isc_histo_t` is thread-safe, it can suffer
from cache contention under heavy load. To avoid this,
an `isc_histomulti_t` contains a histogram per thread,
so updates are local and low-contention.
2023-04-03 12:08:05 +01:00
Tony Finch
82213a48cf Add isc_histo for histogram statistics
This is an adaptation of my `hg64` experiments for use in BIND.

As well as renaming everything according to ISC style, I have
written some more extensive tests that ensure the edge cases are
correct and the fenceposts are in the right places.

I have added utility functions for working with precision in terms of
decimal significant figures as well as this code's native binary.
2023-04-03 12:08:05 +01:00
Ondřej Surý
3a6a0fa867 Replace DE_CONST(k, v) with v = UNCONST(k) macro
Replace the complicated DE_CONST macro that required union with much
simple reference-dereference trick in the UNCONST() macro.
2023-04-03 10:25:56 +00:00
Ondřej Surý
4ec9c4a1db Cleanup the last Windows / MSC ifdefs and comments
Cleanup the remnants of MS Compiler bits from <isc/refcount.h>, printing
the information in named/main.c, and cleanup some comments about Windows
that no longer apply.

The bits in picohttpparser.{h,c} were left out, because it's not our
code.
2023-04-03 09:06:20 +00:00
Mark Andrews
2abd6c7ab4 Handle MD5 not being supported by lib crypto
When initialising the message digests in lib/isc/md.c no
longer assume that the initialisation cannot fail.
2023-04-03 12:44:27 +10:00
Mark Andrews
a3172c8f9c Don't check for OPENSSL_cleanup failures by default
OPENSSL_cleanup is supposed to free all remaining memory in use
provided the application has cleaned up properly.  This is not the
case on some operating systems.  Silently ignore memory that is
freed after OPENSSL_cleanup has been called.
2023-04-03 12:44:27 +10:00
Mark Andrews
e029803704 Handle fatal and FIPS provider interactions
When fatal is called we may be holding memory allocated by OpenSSL.
This may result in the reference count for the FIPS provider not
going to zero and the shared library not being unloaded during
OPENSSL_cleanup.  When the shared library is ultimately unloaded,
when all remaining dynamically loaded libraries are freed, we have
already destroyed the memory context we where using to track memory
leaks / late frees resulting in INSIST being called.

Disable triggering the INSIST when fatal has being called.
2023-04-03 12:44:27 +10:00
Mark Andrews
5a2e82557e Define isc_fips_mode() and isc_fips_set_mode()
isc_fips_mode() determines if the process is running in FIPS mode

isc_fips_set_mode() sets the process into FIPS mode
2023-04-03 12:05:28 +10:00
Tony Finch
555690a3c9 Simplify thread spawning
The `isc_trampoline` module had a lot of machinery to support stable
thread IDs for use by hazard pointers. But the hazard pointer code
is gone, and the `isc_loop` module now has its own per-loop thread
IDs.

The trampoline machinery seems over-complicated for its remaining
tasks, so move the per-thread initialization into `isc/thread.c`,
and delete the rest.
2023-03-31 17:21:52 +01:00
Ondřej Surý
a5f5f68502 Refactor isc_time_now() to return time, and not result
The isc_time_now() and isc_time_now_hires() were used inconsistently
through the code - either with status check, or without status check,
or via TIME_NOW() macro with RUNTIME_CHECK() on failure.

Refactor the isc_time_now() and isc_time_now_hires() to always fail when
getting current time has failed, and return the isc_time_t value as
return value instead of passing the pointer to result in the argument.
2023-03-31 15:02:06 +02:00
Ondřej Surý
263d232c79 Replace isc_fsaccess API with more secure file creation
The isc_fsaccess API was created to hide the implementation details
between POSIX and Windows APIs.  As we are not supporting the Windows
APIs anymore, it's better to drop this API used in the DST part.

Moreover, the isc_fsaccess was setting the permissions in an insecure
manner - it operated on the filename, and not on the file descriptor
which can lead to all kind of attacks if unpriviledged user has read (or
even worse write) access to key directory.

Replace the code that operates on the private keys with code that uses
mkstemp(), fchmod() and atomic rename() at the end, so at no time the
private key files have insecure permissions.
2023-03-31 12:52:59 +00:00
Ondřej Surý
aca7dd3961 Add isc_os_umask() function to get current umask
As it's impossible to get the current umask without modifying it at the
same time, initialize the current umask at the program start and keep
the loaded value internally.  Add isc_os_umask() function to access the
starttime umask.
2023-03-31 12:52:59 +00:00
Ondřej Surý
4bd6096d4b Remove isc_stdtime_get() macro
Now that isc_stdtime_get() macro is unused, remove it from the header
file.
2023-03-31 13:33:16 +02:00
Ondřej Surý
46f06c1d6e Apply the semantic patch to remove isc_stdtime_get()
This is a simple replacement using the semantic patch from the previous
commit and as added bonus, one removal of previously undetected unused
variable in named/server.c.
2023-03-31 13:32:56 +02:00
Ondřej Surý
c11af0448a Provide isc_stdtime_now(void) that returns value
As isc_stdtime_get() cannot fail, the API seems to be too complicated,
add new isc_stdtime_now() that returns the unixtime as a return value.
2023-03-31 13:16:28 +02:00
Tony Finch
194621a74e Fix a crash when dig or host receive a signal
When the loopmanager is shutting down following a signal,
`dig` and `host` should stop cleanly. Before this commit
they were oblivious to ISC_R_SHUTTINGDOWN.

The `isc_signal` callbacks now report this kind of mistake
with a stack backtrace.
2023-03-31 09:52:54 +00:00
Ondřej Surý
2c0a9575d7 Replace __attribute__((unused)) with ISC_ATTR_UNUSED attribute macro
Instead of marking the unused entities with UNUSED(x) macro in the
function body, use a `ISC_ATTR_UNUSED` attribute macro that expans to
C23 [[maybe_unused]] or __attribute__((__unused__)) as fallback.
2023-03-30 23:29:25 +02:00
Ondřej Surý
1176bf0552 Use C23 attributes if available, add ISC_ATTR_UNUSED
Use C23 attribute styles if available:

  * Add new ISC_ATTR_UNUSED attribute macro that either expands to C23's
    [[maybe_unused]] or __attribute__((__unused__));

  * Add default expansion of the `noreturn` to [[noreturn]] if available;

  * Move the FALLTHROUGH from <isc/util.h> to <isc/attributes.h>
2023-03-30 22:43:39 +02:00
Artem Boldariev
43e21d653f TLS Stream: remove incorrect/obsolete INSIST()s from tls_do_bio()
With the changes to tls_try_handshake() made in
2846888c57 there are some incorrect
INSISTS() related to handshake handling which better to be removed.
2023-03-30 18:21:50 +03:00
Ondřej Surý
2846888c57 Attach the accept "client" socket to .listener member of the socket
When accepting a TCP connection in the higher layers (tlsstream,
streamdns, and http) attach to the socket the connection was accepted
on, and use this socket instead of the parent listening socket.

This has an advantage - accessing the sock->listener now doesn't break
the thread boundaries, so we can properly check whether the socket is
being closed without requiring .closing member to be atomic_bool.
2023-03-30 16:10:08 +02:00
Ondřej Surý
45365adb32 Convert sock->active to non-atomic variable, cleanup rchildren
The last atomic_bool variable sock->active was converted to non-atomic
bool by properly handling the listening socket case where we were
checking parent socket instead of children sockets.

This is no longer necessary as we properly set the .active to false on
the children sockets.

Additionally, cleanup the .rchildren - the atomic variable was used for
mutex+condition to block until all children were listening, but that's
now being handled by a barrier.

Finally, just remove dead .self and .active_child_connections members of
the netmgr socket.
2023-03-30 16:10:08 +02:00
Ondřej Surý
e1a4572fd6 Refactor the use of atomics in netmgr
Now that everything runs on their own loop and we don't cross the thread
boundaries (with few exceptions), most of the atomic_bool variables used
to track the socket state have been unatomicized because they are always
accessed from the matching thread.

The remaining few have been relaxed: a) the sock->active is now using
acquire/release memory ordering; b) the various global limits are now
using relaxed memory ordering - we don't really care about the
synchronization for those.
2023-03-30 16:10:08 +02:00
Ondřej Surý
f5fc224af3 Add isc_async_current() macro to run job on current loop
Previously, isc_job_run() could have been used to run the job on the
current loop and the isc_job_run() would take care of allocating and
deallocating the job.  After the change in this MR, the isc_job_run()
is more complicated to use, so we introduce the isc_async_current()
macro to suplement isc_async_run() when we need to run the job on the
current loop.
2023-03-30 16:07:41 +02:00
Ondřej Surý
1844590ad9 Refactor isc_job_run to not-make any allocations
Change the isc_job_run() to not-make any allocations.  The caller must
make sure that it allocates isc_job_t - usually as part of the argument
passed to the callback.

For simple jobs, using isc_async_run() is advised as it allocates its
own separate isc_job_t.
2023-03-30 16:00:52 +02:00
Ondřej Surý
639d5065a3 Refactor the isc__nm_uvreq_t to have idle callback
Change the isc__nm_uvreq_t to have the idle callback as a separate
member as we always need to use it to properly close the uvreq.

Slightly refactor uvreq_put and uvreq_get to remove the unneeded
arguments - in uvreq_get(), we always use sock->worker, and in
uvreq_put, we always use req->sock, so there's not reason to pass those
extra arguments.
2023-03-29 21:16:44 +02:00
Ondřej Surý
476198f26c Use uv_idle API for calling asynchronous connect/read/send callback
Instead of using isc_job_run() that's quite heavy as it allocates memory
for every new job, add uv_idle_t to uvreq union, and use uv_idle API
directly to execute the connect/read/send callback without any
additional allocations.
2023-03-29 21:16:44 +02:00
Ondřej Surý
670df3da74 Re-add the comment to streamdns_readmore()
Put the comment back, so it's more obvious that we are only restarting
timer when there's a last handle attached to the socket; there has to be
always at least one.
2023-03-29 21:16:44 +02:00