4071 Commits

Author SHA1 Message Date
Ondřej Surý
8d4ba2b77f Run .closehandle_cb asynchrounosly in nmhandle_detach_cb()
When sock->closehandle_cb is set, we need to run nmhandle_detach_cb()
asynchronously to ensure correct order of multiple packets processing in
the isc__nm_process_sock_buffer().  When not run asynchronously, it
would cause:

  a) out-of-order processing of the return codes from processbuffer();

  b) stack growth because the next TCP DNS message read callback will
     be called from within the current TCP DNS message read callback.

The sock->closehandle_cb is set to isc__nm_resume_processing() for TCP
sockets which calls isc__nm_process_sock_buffer().  If the read callback
(called from isc__nm_process_sock_buffer()->processbuffer()) doesn't
attach to the nmhandle (f.e. because it wants to drop the processing or
we send the response directly via uv_try_write()), the
isc__nm_resume_processing() (via .closehandle_cb) would call
isc__nm_process_sock_buffer() recursively.

The below shortened code path shows how the stack can grow:

 1: ns__client_request(handle, ...);
 2: isc_nm_tcpdns_sequential(handle);
 3: ns_query_start(client, handle);
 4:   query_lookup(qctx);
 5:     query_send(qctcx->client);
 6:       isc__nmhandle_detach(&client->reqhandle);
 7:         nmhandle_detach_cb(&handle);
 8:           sock->closehandle_cb(sock); // isc__nm_resume_processing
 9:             isc__nm_process_sock_buffer(sock);
10:               processbuffer(sock); // isc__nm_tcpdns_processbuffer
11:                 isc_nmhandle_attach(req->handle, &handle);
12:                 isc__nm_readcb(sock, req, ISC_R_SUCCESS);
13:                   isc__nm_async_readcb(NULL, ...);
14:                     uvreq->cb.recv(...); // ns__client_request

Instead, if 'sock->closehandle_cb' is set, we need to run detach the
handle asynchroniously in 'isc__nmhandle_detach', so that on line 8 in
the code flow above does not start this recursion. This ensures the
correct order when processing multiple packets in the function
'isc__nm_process_sock_buffer()' and prevents the stack growth.

When not run asynchronously, the out-of-order processing leaves the
first TCP socket open until all requests on the stream have been
processed.

If the pipelining is disabled on the TCP via `keep-response-order`
configuration option, named would keep the first socket in lingering
CLOSE_WAIT state when the client sends an incomplete packet and then
closes the connection from the client side.
2022-03-03 13:33:00 +01:00
Aram Sargsyan
2325ed66c5 Remove EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free() shims
LibreSSL 3.5.0 fails to compile with these shims. We could have just
removed the LibreSSL check from the pre-processor condition, but it
seems that these shims are no longer needed because all the supported
versions of OpenSSL and LibreSSL have those functions.

According to EVP_ENCRYPTINIT(3) manual page in LibreSSL,
EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free() first appeared in
OpenSSL 0.9.8b, and have been available since OpenBSD 4.5.

(cherry picked from commit a3789053682b57a2031de8c544134f1923e76cf3)
2022-03-02 09:31:50 +00:00
Mark Andrews
0b6af23d61 Grow the lex token buffer in one more place
when parsing key pairs, if the '=' character fell at max_token
a protective INSIST preventing buffer overrun could be triggered.
Attempt to grow the buffer immediately before the INSIST.

Also removed an unnecessary INSIST on the opening double quote
of key buffer pair.

(cherry picked from commit 4c356d2770)
2022-03-02 01:04:40 +00:00
Ondřej Surý
ac5952aee8 Handle TCP sockets in isc__nmsocket_reset()
The isc__nmsocket_reset() was missing a case for raw TCP sockets (used
by RNDC and DoH) which would case a assertion failure when write timeout
would be triggered.

TCP sockets are now also properly handled in isc__nmsocket_reset().

(cherry picked from commit b220fb32bd)
2022-02-28 11:44:47 +01:00
Ondřej Surý
fe5cd40a3a Disable inactive uvreqs caching when compiled with sanitizers
When isc__nm_uvreq_t gets deactivated, it could be just put onto array
stack to be reused later to save some initialization time.
Unfortunately, this might hide some use-after-free errors.

Disable the inactive uvreqs caching when compiled with Address or
Thread Sanitizer.

(cherry picked from commit be339b3c83)
2022-02-24 00:16:31 +01:00
Ondřej Surý
55780afdb9 Disable inactive handles caching when compiled with sanitizers
When isc_nmhandle_t gets deactivated, it could be just put onto array
stack to be reused later to safe some initialization time.
Unfortunately, this might hide some use-after-free errors.

Disable the inactive handles caching when compiled with Address or
Thread Sanitizer.

(cherry picked from commit 92cce1da65)
2022-02-24 00:10:18 +01:00
Ondřej Surý
7765263e68 Remove active handles tracking from isc__nmsocket_t
The isc__nmsocket_t has locked array of isc_nmhandle_t that's not used
for anything.  The isc__nmhandle_get() adds the isc_nmhandle_t to the
locked array (and resized if necessary) and removed when
isc_nmhandle_put() finally destroys the handle.  That's all it does, so
it serves no useful purpose.

Remove the .ah_handles, .ah_size, and .ah_frees members of the
isc__nmsocket_t and .ah_pos member of the isc_nmhandle_t struct.

(cherry picked from commit e2555a306f)
2022-02-23 23:50:54 +01:00
Ondřej Surý
7b8e265a40 Delay isc__nm_uvreq_t deallocation to connection callback
When the TCP, TCPDNS or TLSDNS connection times out, the isc__nm_uvreq_t
would be pushed into sock->inactivereqs before the uv_tcp_connect()
callback finishes.  Because the isc__nmsocket_t keeps the list of
inactive isc__nm_uvreq_t, this would cause use-after-free only when the
sock->inactivereqs is full (which could never happen because the failure
happens in connection timeout callback) or when the sock->inactivereqs
mechanism is completely removed (f.e. when running under Address or
Thread Sanitizer).

Delay isc__nm_uvreq_t deallocation to the connection callback and only
signal the connection callback should be called by shutting down the
libuv socket from the connection timeout callback.

(cherry picked from commit 3268627916)
2022-02-23 23:36:09 +01:00
Ondřej Surý
af2bddc242 Properly free up enqueued netievents in nm_destroy()
When the isc_netmgr is being destroyed, the normal and priority queues
should be dequeued and netievents properly freed.  This wasn't the case.

(cherry picked from commit 88418c3372)
2022-02-23 22:53:41 +01:00
Ondřej Surý
914a7e14e2 Add network manager based timer API
This commits adds API that allows to create arbitrary timers associated
with the network manager handles.

(cherry picked from commit 3c7b04d015)
2022-02-17 22:59:24 +01:00
Ondřej Surý
3f24bd2bce Update writetimeout to be T_IDLE in netmgr_test.c
Use the isc_nmhandle_setwritetimeout() function in the netmgr unit test
to allow more time for writing and reading the responses because some of
the intervals that are used in the unit tests are really small leaving a
little room for any delays.

(cherry picked from commit ee359d6ffa)
2022-02-17 11:26:16 +01:00
Ondřej Surý
1d0f2eb2c4 Add isc_nmhandle_setwritetimeout() function
In some situations (unit test and forthcoming XFR timeouts MR), we need
to modify the write timeout independently of the read timeout.  Add a
isc_nmhandle_setwritetimeout() function that could be called before
isc_nm_send() to specify a custom write timeout interval.

(cherry picked from commit a89d9e0fa6)
2022-02-17 11:26:16 +01:00
Ondřej Surý
6a88131d03 Add TCP, TCPDNS and TLSDNS write timer
When the outgoing TCP write buffers are full because the other party is
not reading the data, the uv_write() could wait indefinitely on the
uv_loop and never calling the callback.  Add a new write timer that uses
the `tcp-idle-timeout` value to interrupt the TCP connection when we are
not able to send data for defined period of time.

(cherry picked from commit 408b362169)
2022-02-17 10:05:24 +01:00
Ondřej Surý
11ae4399d9 Add uv_tcp_close_reset compat
The uv_tcp_close_reset() function was added in libuv 1.32.0 and since we
support older libuv releases, we have to add a shim uv_tcp_close_reset()
implementation loosely based on libuv.

(cherry picked from commit cd3b58622c)
2022-02-17 09:50:10 +01:00
Ondřej Surý
eb2463115f Rename sock->timer to sock->read_timer
Before adding the write timer, we have to remove the generic sock->timer
to sock->read_timer.  We don't touch the function names to limit the
impact of the refactoring.

(cherry picked from commit 45a73c113f)
2022-02-17 09:50:07 +01:00
Ondřej Surý
1c564b808f Use UV_RUNTIME_CHECK() as appropriate
Replace the RUNTIME_CHECK() calls for libuv API calls with
UV_RUNTIME_CHECK() to get more detailed error message when
something fails and should not.

(cherry picked from commit 8715be1e4b)
2022-02-16 11:48:30 +01:00
Ondřej Surý
88751da114 Add UV_RUNTIME_CHECK() macro to print uv_strerror()
When libuv functions fail, they return correct return value that could
be useful for more detailed debugging.  Currently, we usually just check
whether the return value is 0 and invoke assertion error if it doesn't
throwing away the details why the call has failed.  Unfortunately, this
often happen on more exotic platforms.

Add a UV_RUNTIME_CHECK() macro that can be used to print more detailed
error message (via uv_strerror() before ending the execution of the
program abruptly with the assertion.

(cherry picked from commit 62e15bb06d)
2022-02-16 11:46:10 +01:00
Ondřej Surý
6b2d9dcfd9 Log when starting and ending task exclusive mode
The task exclusive mode stops all processing (tasks and networking IO)
except the designated exclusive task events.  This has impact on the
operation of the server.  Add log messages indicating when we start the
exclusive mode, and when we end exclusive task mode.

(cherry picked from commit b9cb29076f)
2022-02-10 21:22:46 +01:00
Ondřej Surý
ad5869ac6c Remove unused functions from isc_thread API
The isc_thread_setaffinity call was removed in !5265 and we are not
going to restore it because it was proven that the performance is better
without it.  Additionally, remove the already disabled cpu system test.

The isc_thread_setconcurrency function is unused and also calling
pthread_setconcurrency() on Linux has no meaning, formerly it was
added because of Solaris in 2001 and it was removed when taskmgr was
refactored to run on top of netmgr in !4918.

(cherry picked from commit 0500345513)
2022-02-09 18:09:48 +01:00
Ondřej Surý
00e8bfcdfc Add log message when hard quota is reached in TCP accept
When isc_quota_attach_cb() API returns ISC_R_QUOTA (meaning hard quota
was reached) the accept_connection() would return without logging a
message about quota reached.

Change the connection callback to log the quota reached message.

(cherry picked from commit 2ae84702ad)
2022-02-01 21:06:43 +01:00
Petr Špaček
dbe0778b67 extend DLZ interface and example with ECS support
Apparently we forgot about DLZ when updating DNS_CLIENTINFO_VERSION
constant for ECS, which is at value "3" since ECS was introduced.

The code in example drivers and tests now hardcodes version numbers
2 (without ECS) and 3 (with ECS) depending on what a given code path
requires.

(cherry picked from commit f81debe1c8)
2022-01-27 16:20:55 -08:00
Evan Hunt
464b09a804 add UV_ENOTSUP to isc___nm_uverr2result()
This error code is now mapped to ISC_R_FAMILYNOSUPPORT.

(cherry picked from commit be0bc24c7f)
2022-01-17 11:47:12 +01:00
Ondřej Surý
86f9b16fd7 Revert "Always enqueue isc__nm_tcp_resumeread()"
The commit itself is harmless, but at the same time it is also useless,
so we are reverting it.

This reverts commit 11c869a3d5.

(cherry picked from commit 0a4e91ee47)
2022-01-13 21:39:57 +01:00
Ondřej Surý
5b02f5a8a0 Fix the UDP recvmmsg support
Previously, the netmgr/udp.c tried to detect the recvmmsg detection in
libuv with #ifdef UV_UDP_<foo> preprocessor macros.  However, because
the UV_UDP_<foo> are not preprocessor macros, but enum members, the
detection didn't work.  Because the detection didn't work, the code
didn't have access to the information when we received the final chunk
of the recvmmsg and tried to free the uvbuf every time.  Fortunately,
the isc__nm_free_uvbuf() had a kludge that detected attempt to free in
the middle of the receive buffer, so the code worked.

However, libuv 1.37.0 changed the way the recvmmsg was enabled from
implicit to explicit, and we checked for yet another enum member
presence with preprocessor macro, so in fact libuv recvmmsg support was
never enabled with libuv >= 1.37.0.

This commit changes to the preprocessor macros to autoconf checks for
declaration, so the detection now works again.  On top of that, it's now
possible to cleanup the alloc_cb and free_uvbuf functions because now,
the information whether we can or cannot free the buffer is available to
us.

(cherry picked from commit 7370725008)
2022-01-13 21:38:43 +01:00
Ondřej Surý
2bf7921c7e Update the copyright information in all files in the repository
This commit converts the license handling to adhere to the REUSE
specification.  It specifically:

1. Adds used licnses to LICENSES/ directory

2. Add "isc" template for adding the copyright boilerplate

3. Changes all source files to include copyright and SPDX license
   header, this includes all the C sources, documentation, zone files,
   configuration files.  There are notes in the doc/dev/copyrights file
   on how to add correct headers to the new files.

4. Handle the rest that can't be modified via .reuse/dep5 file.  The
   binary (or otherwise unmodifiable) files could have license places
   next to them in <foo>.license file, but this would lead to cluttered
   repository and most of the files handled in the .reuse/dep5 file are
   system test files.

(cherry picked from commit 58bd26b6cf)
2022-01-11 12:22:09 +01:00
Ondřej Surý
8590251f5a Always enqueue isc__nm_tcp_resumeread()
The isc__nm_tcp_resumeread() was using maybe_enqueue function to enqueue
netmgr event which could case the read callback to be executed
immediately if there was enough data waiting in the TCP queue.

If such thing would happen, the read callback would be called before the
previous read callback was finished and the worker receive buffer would
be still marked "in use" causing a assertion failure.

This would affect only raw TCP channels, e.g. rndc and http statistics.

(cherry picked from commit 11c869a3d5)
2022-01-06 20:00:44 +01:00
Ondřej Surý
5be356760d Remove taskmgr->excl_lock, fix the locking for taskmgr->exiting
While doing code review, it was found that the taskmgr->exiting is set
under taskmgr->lock, but accessed under taskmgr->excl_lock in the
isc_task_beginexclusive().

Additionally, before the change that moved running the tasks to the
netmgr, the task_ready() subrouting of isc_task_detach() would lock
mgr->lock, requiring the mgr->excl to be protected mgr->excl_lock
to prevent deadlock in the code.  After !4918 has been merged, this is
no longer true, and we can remove taskmgr->excl_lock and use
taskmgr->lock in its stead.

Solve both issues by removing the taskmgr->excl_lock and exclusively use
taskmgr->lock to protect both taskmgr->excl and taskmgr->exiting which
now doesn't need to be atomic_bool, because it's always accessed from
within the locked section.

(cherry picked from commit e705f213ca)
2022-01-06 17:56:45 +01:00
Ondřej Surý
9ec7d78d16 On shutdown, return ISC_R_SHUTTINGDOWN from isc_taskmgr_excltask()
The isc_taskmgr_excltask() would return ISC_R_NOTFOUND either when the
exclusive task was not set (yet) or when the taskmgr is shutting down
and the exclusive task has been already cleared.

Distinguish between the two states and return ISC_R_SHUTTINGDOWN when
the taskmgr is being shut down instead of ISC_R_NOTFOUND.

(cherry picked from commit f9d90159b8)
2022-01-06 17:56:45 +01:00
Ondřej Surý
1f7d2d53f0 Disable the internal memory allocator by default
For small sized allocations, the internal allocator gets the memory in
bigger blobs that gets splits into right-sized chunks.  This increases
speed of small allocations and reduced the fragmentation, but such
memory is never released back to the operating system.

Disable the internal allocator by default, and add new `-M internal`
command line option to `named`.
2021-12-15 13:29:19 +01:00
Ondřej Surý
c96b6eb5ec Don't use mem freelists for isc_mempools
Previously, with BIND 9 internal allocator, when isc_mempool_put() would
return memory to the allocator, it would not be freed, but it would be
returned to the "freelists" and the memory would not be released to the
operating system.

Change the isc_mempool_get() and isc_mempool_put() to avoid the internal
allocator (mem_getunlocked() and mem_putunlocked()).
2021-12-15 13:29:19 +01:00
Ondřej Surý
6abebaaad9 Remove locking mechanism from the isc_mempool
Now, that all the locked mempools have been replaced with simple isc_mem
context, remove unused optional locking from isc_mempool API.
2021-12-15 13:29:19 +01:00
Ondřej Surý
974f2f6ace Replace locked mempools with memory contexts
Current mempools are kind of hybrid structures - they serve two
purposes:

 1. mempool with a lock is basically static sized allocator with
    pre-allocated free items

 2. mempool without a lock is a doubly-linked list of preallocated items

The first kind of usage could be easily replaced with jemalloc small
sized arena objects and thread-local caches.

The second usage not-so-much and we need to keep this (in
libdns:message.c) for performance reasons.
2021-12-15 13:29:19 +01:00
Matthijs Mekking
3c77a51f6b Add OPENSSL_cleanup to tls_shutdown function
This prevents a direct leak in OPENSSL_init_crypto (called from
OPENSSL_init_ssl).

Add shim version of OPENSSL_cleanup because it is missing in LibreSSL on
OpenBSD.

(cherry picked from commit 89f4f8f0c8)
2021-12-09 10:47:56 +01:00
Ondřej Surý
d5cdcf924a Stop leaking mutex in nmworker and cond in nm socket
On FreeBSD, the pthread primitives are not solely allocated on stack,
but part of the object lives on the heap.  Missing pthread_*_destroy
causes the heap memory to grow and in case of fast lived object it's
possible to run out-of-memory.

Properly destroy the leaking mutex (worker->lock) and
the leaking condition (sock->cond).

(cherry picked from commit 57d0fabadd)
2021-12-08 18:19:37 +01:00
Ondřej Surý
75c484e36d Improve the logging on failed TCP accept
Previously, when TCP accept failed, we have logged a message with
ISC_LOG_ERROR level.  One common case, how this could happen is that the
client hits TCP client quota and is put on hold and when resumed, the
client has already given up and closed the TCP connection.  In such
case, the named would log:

    TCP connection failed: socket is not connected

This message was quite confusing because it actually doesn't say that
it's related to the accepting the TCP connection and also it logs
everything on the ISC_LOG_ERROR level.

Change the log message to "Accepting TCP connection failed" and for
specific error states lower the severity of the log message to
ISC_LOG_INFO.

(cherry picked from commit 20ac73eb22)
2021-12-02 14:19:46 +01:00
Ondřej Surý
3d4ec2f244 Add isc_time_add and isc_time_subtract unit test
The isc_time_add() and isc_time_subtract() didn't have a unit test, add
the unit test with couple of edge case vectors to check whether overflow
and underflow is correctly handled.

(cherry picked from commit 04511736a0)
2021-10-21 09:51:53 +02:00
Ondřej Surý
b58611a08b Fix isc_time_add() overflow
The isc_time_add() could overflow when t.seconds + i.seconds == UINT_MAX
and t.nanoseconds + i.nanoseconds >= NS_PER_S.

Fix the overflow in isc_time_add(), and simplify the ISC_R_RANGE checks
both in isc_time_add() and isc_time_subtract() functions.

(cherry picked from commit 8c05f12bc8)
2021-10-21 09:51:48 +02:00
Ondřej Surý
093cd31ae2 Update the source code formatting using clang-format-13
clang-format-13 fixed some of the formatting that clang-format-12 got
wrong.  Update the formatting.

(cherry picked from commit ed95f9fba3)
2021-10-12 11:31:55 +02:00
Mark Andrews
5dff412a08 Address use before NULL check warning of ievent->sock
Reorder REQUIRE checks to ensure ievent->sock is checked earlier

(cherry picked from commit 8fc9bb8e8e)
2021-09-29 11:43:14 +10:00
Mark Andrews
addd580b0a Address use before NULL check warning of uvreq
move dereference of uvreq until the after NULL check.

(cherry picked from commit 7079829b84)
2021-09-29 11:43:14 +10:00
Aram Sargsyan
18514a43d5 Remove dead code
Remove dead code from the USE_DEVPOLL branch in libisc's unix/socket.c
2021-09-08 12:52:33 +00:00
Mark Andrews
9a01b867af Fix the definition of atomic_load_explicit in the win32 shim
incorrect parentheses result in incorrect sizeof test
2021-09-01 10:26:16 +10:00
Ondřej Surý
ec64f4492b Initialize the main thread trampoline for Windows Service process
When BIND is running as a Windows Service the ISC library's
initializations initiated by the DLLMain loading procedure are
happening under the Windows Service Manager thread instead of
BIND's main thread.

This commit will make sure that BIND's main thread trampoline has
been initialized before running the main() function.
2021-08-31 17:53:30 +00:00
Evan Hunt
4f87dcac1a replace per-protocol keepalive functions with a common one
this commit removes isc__nm_tcpdns_keepalive(); the keepalive
value for this protocol and for TCP will now be set directly from
isc_nmhandle_keepalive().

(cherry picked from commit fc6f751fbe)
2021-08-27 13:20:06 -07:00
Evan Hunt
6b7e4e753a enable keepalive when the keepalive EDNS option is seen
previously, receiving a keepalive option had no effect on how
long named would keep the connection open; there was a place to
configure the keepalive timeout but it was never used. this commit
corrects that.

this also fixes an error in isc__nm_tcpdns_keepalive()
in which the sense of a REQUIRE test was reversed; previously this
error had not been noticed because the functions were not being
used.

(cherry picked from commit 7867b8b57d)
2021-08-27 13:20:06 -07:00
Evan Hunt
de00df3669 cleanup netmgr-int.h
- fix some duplicated and out-of-order prototypes declared in
  netmgr-int.h
- rename isc_nm_tcpdns_keepalive to isc__nm_tcpdns_keepalive as
  it's for internal use

(cherry picked from commit 19e24e22f5)
2021-08-27 13:20:02 -07:00
Matthijs Mekking
4a1987a380 Add a function isc_stats_resize
Add a new function to resize the number of counters in a statistics
counter structure. This will be needed when we keep track of DNSSEC
sign statistics and new keys are introduced due to a rollover.

(cherry picked from commit 9acce8a82a)
2021-08-24 09:51:45 +02:00
Matthijs Mekking
4f08beb1de Add stats unit test
Add a simple stats unit test that tests the existing library functions
isc_stats_ncounters, isc_stats_increment, isc_stats_decrement,
isc_stats_set, and isc_stats_update_if_greater.

(manually picked from commit 0bac9c7c5c)
2021-08-24 09:27:38 +02:00
Michal Nowak
ae370e3e61 Fix typos in lib/isc/trampoline_p.h 2021-08-19 07:20:15 +02:00
Ondřej Surý
607f8d114e Disable the Path MTU Discover on UDP Sockets
Instead of disabling the fragmentation on the UDP sockets, we now
disable the Path MTU Discovery by setting IP(V6)_MTU_DISCOVER socket
option to IP_PMTUDISC_OMIT on Linux and disabling IP(V6)_DONTFRAG socket
option on FreeBSD.  This option sets DF=0 in the IP header and also
ignores the Path MTU Discovery.

As additional mitigation on Linux, we recommend setting
net.ipv4.ip_no_pmtu_disc to Mode 3:

    Mode 3 is a hardend pmtu discover mode. The kernel will only accept
    fragmentation-needed errors if the underlying protocol can verify
    them besides a plain socket lookup. Current protocols for which pmtu
    events will be honored are TCP, SCTP and DCCP as they verify
    e.g. the sequence number or the association. This mode should not be
    enabled globally but is only intended to secure e.g. name servers in
    namespaces where TCP path mtu must still work but path MTU
    information of other protocols should be discarded. If enabled
    globally this mode could break other protocols.
2021-08-19 07:20:15 +02:00