2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-28 04:58:04 +00:00

91 Commits

Author SHA1 Message Date
Ondřej Surý
78886d4bed Fix the statistic counter underflow in ns_client_t
In case of normal fetch, the .recursionquota is attached and
ns_statscounter_recursclients is incremented when the fetch is created.  Then
the .recursionquota is detached and the counter decremented in the
fetch_callback().

In case of prefetch or rpzfetch, the quota is attached, but the counter is not
incremented.  When we reach the soft-quota, the function returns early but don't
detach from the quota, and it gets destroyed during the ns_client_endrequest(),
so no memory was leaked.

But because the ns_statscounter_recursclients is only incremented during the
normal fetch the counter would be incorrectly decremented on two occassions:

1) When we reached the softquota, because the quota was not properly detached
2) When the prefetch or rpzfetch was cancelled mid-flight and the callback
   function was never called.
2020-04-03 19:41:46 +02:00
Witold Kręcicki
df3dbdff81 Destroy query in killoldestquery under a lock.
Fixes a race between ns_client_killoldestquery and ns_client_endrequest -
killoldestquery takes a client from `recursing` list while endrequest
destroys client object, then killoldestquery works on a destroyed client
object. Prevent it by holding reclist lock while cancelling query.
2020-03-05 08:13:50 +00:00
Evan Hunt
0b76d8a490 comments 2020-02-28 08:46:16 +01:00
Witold Kręcicki
4b6a064972 Don't define NS_CLIENT_TRACE by default 2020-02-28 08:46:16 +01:00
Witold Kręcicki
8c6c07286f Remove some stale fields from ns_client_t; make sendbuf allocated on heap 2020-02-28 08:46:16 +01:00
Witold Kręcicki
938b61405b Don't check if the client is on recursing list (requires locking) if it's not RECURSING 2020-02-28 08:46:16 +01:00
Witold Kręcicki
b0888ff039 Don't issue ns_client_endrequest on a NS_CLIENTSTATE_READY client.
Fix a potential assertion failure on shutdown in ns__client_endrequest.
Scenario:
1. We are shutting down, interface->clientmgr is gone.
2. We receive a packet, it gets through ns__client_request
3. mgr == NULL, return
4. isc_nmhandle_detach calls ns_client_reset_cb
5. ns_client_reset_cb calls ns_client_endrequest
6. INSIST(client->state == NS_CLIENTSTATE_WORKING ||
          client->state == NS_CLIENTSTATE_RECURSING) is not met
   - we haven't started processing this packet so
   client->state == NS_CLIENTSTATE_READY.
As a solution - don't do anything in ns_client_reset_cb if the client
is still in READY state.
2020-02-26 12:15:01 +00:00
Witold Kręcicki
952f7b503d Use thread-friendly mctxpool and taskpool in ns_client.
Make ns_client mctxpool more thread-friendly by sharding it by
netmgr threadid, use task pool also sharded by thread id to avoid
lock contention.
2020-02-18 10:31:13 +01:00
Ondřej Surý
5777c44ad0 Reformat using the new rules 2020-02-14 09:31:05 +01:00
Evan Hunt
e851ed0bb5 apply the modified style 2020-02-13 15:05:06 -08:00
Ondřej Surý
056e133c4c Use clang-tidy to add curly braces around one-line statements
The command used to reformat the files in this commit was:

./util/run-clang-tidy \
	-clang-tidy-binary clang-tidy-11
	-clang-apply-replacements-binary clang-apply-replacements-11 \
	-checks=-*,readability-braces-around-statements \
	-j 9 \
	-fix \
	-format \
	-style=file \
	-quiet
clang-format -i --style=format $(git ls-files '*.c' '*.h')
uncrustify -c .uncrustify.cfg --replace --no-backup $(git ls-files '*.c' '*.h')
clang-format -i --style=format $(git ls-files '*.c' '*.h')
2020-02-13 22:07:21 +01:00
Ondřej Surý
f50b1e0685 Use clang-format to reformat the source files 2020-02-12 15:04:17 +01:00
Ondřej Surý
bc1d4c9cb4 Clear the pointer to destroyed object early using the semantic patch
Also disable the semantic patch as the code needs tweaks here and there because
some destroy functions might not destroy the object and return early if the
object is still in use.
2020-02-09 18:00:17 -08:00
Ondřej Surý
41fe9b7a14 Formatting issues found by local coccinelle run 2020-02-08 03:12:09 -08:00
Ondřej Surý
c73e5866c4 Refactor the isc_buffer_allocate() usage using the semantic patch
The isc_buffer_allocate() function now cannot fail with ISC_R_MEMORY.
This commit removes all the checks on the return code using the semantic
patch from previous commit, as isc_buffer_allocate() now returns void.
2020-02-03 08:29:00 +01:00
Witold Kręcicki
8d6dc8613a clean up some handle/client reference counting errors in error cases.
We weren't consistent about who should unreference the handle in
case of network error. Make it consistent so that it's always the
client code responsibility to unreference the handle - either
in the callback or right away if send function failed and the callback
will never be called.
2020-01-20 22:28:36 +01:00
Witold Kręcicki
dcc0835a3a cleanup properly if we fail to initialize ns_client structure
If taskmgr is shutting down ns_client_setup will fail to create
a task for the newly created client, we weren't cleaning up already
created/attached things (memory context, server, clientmgr).
2020-01-20 22:28:36 +01:00
Witold Kręcicki
eda4300bbb netmgr: have a single source of truth for tcpdns callback
We pass interface as an opaque argument to tcpdns listening socket.
If we stop listening on an interface but still have in-flight connections
the opaque 'interface' is not properly reference counted, and we might
hit a dead memory. We put just a single source of truth in a listening
socket and make the child sockets use that instead of copying the
value from listening socket. We clean the callback when we stop listening.
2020-01-15 17:22:13 +01:00
Ondřej Surý
7c3e342935 Use isc_refcount_increment0() where appropriate 2020-01-14 13:12:13 +01:00
Ondřej Surý
fbf9856f43 Add isc_refcount_destroy() as appropriate 2020-01-14 13:12:13 +01:00
Diego Fronza
ed9853e739 Fix tcp-highwater stats updating
After the network manager rewrite, tcp-higwater stats was only being
updated when a valid DNS query was received over tcp.

It turns out tcp-quota is updated right after a tcp connection is
accepted, before any data is read, so in the event that some client
connect but don't send a valid query, it wouldn't be taken into
account to update tcp-highwater stats, that is wrong.

This commit fix tcp-highwater to update its stats whenever a tcp connection
is established, independent of what happens after (timeout/invalid
request, etc).
2019-12-12 11:23:10 -08:00
Evan Hunt
715afa9c57 add a stats counter for clients dropped due to recursive-clients limit 2019-11-26 17:55:06 +00:00
Evan Hunt
199bd6b623 netmgr: make TCP timeouts configurable
- restore support for tcp-initial-timeout, tcp-idle-timeout,
  tcp-keepalive-timeout and tcp-advertised-timeout configuration
  options, which were ineffective previously.
2019-11-22 16:46:31 -08:00
Evan Hunt
123ee350dc place a limit on pipelined queries that can be processed simultaneously
when the TCPDNS_CLIENTS_PER_CONN limit has been exceeded for a TCP
DNS connection, switch to sequential mode to ensure that memory cannot
be exhausted by too many simultaneous queries.
2019-11-17 18:59:39 -08:00
Ondřej Surý
e95af30b23 Make lib/ns Thread Sanitizer clean 2019-11-17 17:42:41 -08:00
Evan Hunt
b9a5508e52 remove ISC_QUEUE as it is no longer used 2019-11-07 11:55:37 -08:00
Evan Hunt
53f0b6c34d convert ns_client and related objects to use netmgr
- ns__client_request() is now called by netmgr with an isc_nmhandle_t
  parameter. The handle can then be permanently associated with an
  ns_client object.
- The task manager is paused so that isc_task events that may be
  triggred during client processing will not fire until after the netmgr is
  finished with it. Before any asynchronous event, the client MUST
  call isc_nmhandle_ref(client->handle), to prevent the client from
  being reset and reused while waiting for an event to process. When
  the asynchronous event is complete, isc_nmhandle_unref(client->handle)
  must be called to ensure the handle can be reused later.
- reference counting of client objects is now handled in the nmhandle
  object.  when the handle references drop to zero, the client's "reset"
  callback is used to free temporary resources and reiniialize it,
  whereupon the handle (and associated client) is placed in the
  "inactive handles" queue.  when the sysstem is shutdown and the
  handles are cleaned up, the client's "put" callback is called to free
  all remaining resources.
- because client allocation is no longer handled in the same way,
  the '-T clienttest' option has now been removed and is no longer
  used by any system tests.
- the unit tests require wrapping the isc_nmhandle_unref() function;
  when LD_WRAP is supported, that is used. otherwise we link a
  libwrap.so interposer library and use that.
2019-11-07 11:55:37 -08:00
Evan Hunt
64e1a4a398 temporarily move ISC_QUEUE to list.h
The double-locked queue implementation is still currently in use
in ns_client, but will be replaced by a fetch-and-add array queue.
This commit moves it from queue.h to list.h so that queue.h can be
used for the new data structure, and clean up dependencies between
list.h and types.h. Later, when the ISC_QUEUE is no longer is use,
it will be removed completely.
2019-11-07 11:55:37 -08:00
Diego Fronza
66fe8627de Added TCP high-water statistics variable
This variable will report the maximum number of simultaneous tcp clients
that BIND has served while running.

It can be verified by running rndc status, then inspect "tcp high-water:
count", or by generating statistics file, rndc stats, then inspect the
line with "TCP connection high-water" text.

The tcp-highwater variable is atomically updated based on an existing
tcp-quota system handled in ns/client.c.
2019-11-06 09:18:27 +01:00
Ondřej Surý
b4a42a286f lib/ns/client.c: Fix invalid order of DbC checks that could cause dereference before NULL check 2019-10-03 09:04:27 +02:00
Mark Andrews
b59fe46e76 address or suppress cppcheck warnings 2019-09-12 17:59:28 +10:00
Ondřej Surý
4957255d13 Use the semantic patch to change the usage isc_mem_create() to new API 2019-09-12 09:26:09 +02:00
Ondřej Surý
ae83801e2b Remove blocks checking whether isc_mem_get() failed using the coccinelle 2019-07-23 15:32:35 -04:00
Ondřej Surý
a912f31398 Add new default siphash24 cookie algorithm, but keep AES as legacy
This commit changes the BIND cookie algorithms to match
draft-sury-toorop-dnsop-server-cookies-00.  Namely, it changes the Client Cookie
algorithm to use SipHash 2-4, adds the new Server Cookie algorithm using SipHash
2-4, and changes the default for the Server Cookie algorithm to be siphash24.

Add siphash24 cookie algorithm, and make it keep legacy aes as
2019-07-21 15:16:28 -04:00
Witold Kręcicki
afa81ee4e4 Remove all cookie algorithms but AES, which was used as a default, for legacy purposes. 2019-07-21 10:08:14 -04:00
Witold Kręcicki
de73904d03 lib/ns/client: use refcount_t for reference counting 2019-07-09 16:09:36 +02:00
Ondřej Surý
8965a0ba98 Replace atomic operations in bin/named/client.c with isc_refcount reference counting
(cherry picked from commit ef49780d30d3ddc5735cfc32561b678a634fa72f)
(cherry picked from commit e203d4d65a3bbba4303b9f185bd38314c0a3f77c)
2019-04-26 22:14:26 +02:00
Evan Hunt
d809ec6c14 restore allowance for tcp-clients < interfaces
in the "refactor tcpquota and pipeline refs" commit, the counting
of active interfaces was tightened in such a way that named could
fail to listen on an interface if there were more interfaces than
tcp-clients. when checking the quota to start accepting on an
interface, if the number of active clients was above zero, then
it was presumed that some other client was able to handle accepting
new connections. this, however, ignored the fact that the current client
could be included in that count, so if the quota was already exceeded
before all the interfaces were listening, some interfaces would never
listen.

we now check whether the current client has been marked active; if so,
then the number of active clients on the interface must be greater
than 1, not 0.

(cherry picked from commit 02365b87ea0b1ea5ea8b17376f6734c811c95e61)
(cherry picked from commit cae79e1bab677ed1c2ce3adc5d54163a78f0d30b)
2019-04-25 16:32:05 +02:00
Evan Hunt
2f3876d187 refactor tcpquota and pipeline refs; allow special-case overrun in isc_quota
- if the TCP quota has been exceeded but there are no clients listening
  for new connections on the interface, we can now force attachment to the
  quota using isc_quota_force(), instead of carrying on with the quota not
  attached.
- the TCP client quota is now referenced via a reference-counted
  'ns_tcpconn' object, one of which is created whenever a client begins
  listening for new connections, and attached to by members of that
  client's pipeline group. when the last reference to the tcpconn
  object is detached, it is freed and the TCP quota slot is released.
- reduce code duplication by adding mark_tcp_active() function
- convert counters to stdatomic

(cherry picked from commit a8dd133d270873b736c1be9bf50ebaa074f5b38f)
(cherry picked from commit 4a8fc979c49104534cf6be5d81dc54da5b6836c9)
2019-04-25 16:32:05 +02:00
Evan Hunt
a0f4a3fa65 better tcpquota accounting and client mortality checks
- ensure that tcpactive is cleaned up correctly when accept() fails.
- set 'client->tcpattached' when the client is attached to the tcpquota.
  carry this value on to new clients sharing the same pipeline group.
  don't call isc_quota_detach() on the tcpquota unless tcpattached is
  set.  this way clients that were allowed to accept TCP connections
  despite being over quota (and therefore, were never attached to the
  quota) will not inadvertently detach from it and mess up the
  accounting.
- simplify the code for tcpquota disconnection by using a new function
  tcpquota_disconnect().
- before deciding whether to reject a new connection due to quota
  exhaustion, check to see whether there are at least two active
  clients. previously, this was "at least one", but that could be
  insufficient if there was one other client in READING state (waiting
  for messages on an open connection) but none in READY (listening
  for new connections).
- before deciding whether a TCP client object can to go inactive, we
  must ensure there are enough other clients to maintain service
  afterward -- both accepting new connections and reading/processing new
  queries.  A TCP client can't shut down unless at least one
  client is accepting new connections and (in the case of pipelined
  clients) at least one additional client is waiting to read.

(cherry picked from commit 427a2fb4d17bc04ca3262f58a9dcf5c93fc6d33e)
(cherry picked from commit 08968412726d680777de6e596c836c6be07819a1)
2019-04-25 16:32:05 +02:00
Michał Kępień
3c0f8d9146 use reference counter for pipeline groups (v3)
Track pipeline groups using a shared reference counter
instead of a linked list.

(cherry picked from commit 31f392db20207a1b05d6286c3c56f76c8d69e574)
(cherry picked from commit 2211120222b5f008a96145474b7f6749d4307028)
2019-04-25 16:32:05 +02:00
Witold Kręcicki
d989a8b38e tcp-clients could still be exceeded (v2)
the TCP client quota could still be ineffective under some
circumstances.  this change:

- improves quota accounting to ensure that TCP clients are
  properly limited, while still guaranteeing that at least one client
  is always available to serve TCP connections on each interface.
- uses more descriptive names and removes one (ntcptarget) that
  was no longer needed
- adds comments

(cherry picked from commit 9e74969f85329fe26df2fad390468715215e2edd)
(cherry picked from commit d7e84cee0bd7957a0707b86d47c29de4b798d350)
2019-04-25 16:32:05 +02:00
Witold Kręcicki
07c3365b0b fix enforcement of tcp-clients (v1)
tcp-clients settings could be exceeded in some cases by
creating more and more active TCP clients that are over
the set quota limit, which in the end could lead to a
DoS attack by e.g. exhaustion of file descriptors.

If TCP client we're closing went over the quota (so it's
not attached to a quota) mark it as mortal - so that it
will be destroyed and not set up to listen for new
connections - unless it's the last client for a specific
interface.

(cherry picked from commit eafcff07c25bdbe038ae1e4b6660602a080b9395)
(cherry picked from commit 9e7617cc84f465769be1a3f426f30cd516220902)
2019-04-25 16:32:04 +02:00
Evan Hunt
7402615697 force SERVFAIL response in the gotanswer failure case
- named could return FORMERR if parsing iterative responses
  ended with a result code such as DNS_R_OPTERR. instead of
  computing a response code based on the result, in this case
  we now just force the response to be SERVFAIL.
2019-04-22 18:48:19 -07:00
Evan Hunt
1f578cdb12 dnstap: if recursion is not available, log queries as AQ instead of CQ 2019-04-11 15:13:13 -07:00
Witold Kręcicki
aa3da7a232 Clean up client->ecs when we're done with the request. 2019-03-12 13:35:28 -07:00
Ondřej Surý
78d0cb0a7d Use coccinelle to remove explicit '#include <config.h>' from the source files 2019-03-08 15:15:05 +01:00
Mark Andrews
35025b6e88 silently ignore additional keytag options 2019-02-20 19:44:36 -08:00
Mark Andrews
0c42a9c0ab explictly convert ISC_R_NOSPACE from dns_message_parse to DNS_R_FORMERR and remove from dns_result_torcode 2019-01-09 15:19:42 +11:00
Evan Hunt
74683fbc3b use entirely local persistent data in modules
- eliminate qctx->hookdata and client->hookflags.
- use a memory pool to allocate data blobs in the filter-aaaa module,
  and associate them with the client address in a hash table
- instead of detaching the client in query_done(), mark it for deletion
  and then call ns_client_detach() from qctx_destroy(); this ensures
  that it will still exist when the QCTX_DESTROYED hook point is
  reached.
2018-12-06 10:29:12 -08:00