bind9/lib/ns
Michał Kępień 5929411f90 Fix more ns_statscounter_recursclients underflows
Commit aab691d512 did not fix all possible
scenarios in which the ns_statscounter_recursclients counter underflows.
The solution implemented therein can be ineffective e.g. when CNAME
chaining happens with prefetching enabled.

Here is an example recursive resolution scenario in which the
ns_statscounter_recursclients counter can underflow with the current
logic in effect:

 1. Query processing starts, the answer is not found in the cache, so
    recursion is started.  The NS_CLIENTATTR_RECURSING attribute is set.
    ns_statscounter_recursclients is incremented (Δ = +1).

 2. Recursion completes, returning a CNAME.  client->recursionquota is
    non-NULL, so the NS_CLIENTATTR_RECURSING attribute remains set.
    ns_statscounter_recursclients is decremented (Δ = 0).

 3. Query processing restarts.

 4. The current QNAME (the target of the CNAME from step 2) is found in
    the cache, with a TTL low enough to trigger a prefetch.

 5. query_prefetch() attaches to client->recursionquota.
    ns_statscounter_recursclients is not incremented because
    query_prefetch() does not do that (Δ = 0).

 6. Query processing restarts.

 7. The current QNAME (the target of the CNAME from step 4) is not found
    in the cache, so recursion is started.  client->recursionquota is
    already attached to (since step 5) and the NS_CLIENTATTR_RECURSING
    attribute is set (since step 1), so ns_statscounter_recursclients is
    not incremented (Δ = 0).

 8. The prefetch from step 5 completes.  client->recursionquota is
    detached from in prefetch_done().  ns_statscounter_recursclients is
    not decremented because prefetch_done() does not do that (Δ = 0).

 9. Recursion for the current QNAME completes.  client->recursionquota
    is already detached from, i.e. set to NULL (since step 8), and the
    NS_CLIENTATTR_RECURSING attribute is set (since step 1), so
    ns_statscounter_recursclients is decremented (Δ = -1).

Another possible scenario is that after step 7, recursion for the target
of the CNAME from step 4 completes before the prefetch for the CNAME
itself.  fetch_callback() then notices that client->recursionquota is
non-NULL and decrements ns_statscounter_recursclients, even though
client->recursionquota was attached to by query_prefetch() and therefore
not accompanied by an incrementation of ns_statscounter_recursclients.
The net result is also an underflow.

Instead of trying to properly handle all possible orderings of events
set into motion by normal recursion and prefetch-triggered recursion,
adjust ns_statscounter_recursclients whenever the recursive clients
quota is successfully attached to or detached from.  Remove the
NS_CLIENTATTR_RECURSING attribute altogether as its only purpose is made
obsolete by this change.

(cherry picked from commit f7482b68b9)
2022-02-23 14:43:09 +01:00
..
include Fix more ns_statscounter_recursclients underflows 2022-02-23 14:43:09 +01:00
tests Update the copyright information in all files in the repository 2022-01-11 09:05:02 +01:00
client.c Reset the TCP connection when garbage is received 2022-02-17 21:02:02 +01:00
hooks.c Update the copyright information in all files in the repository 2022-01-11 09:05:02 +01:00
interfacemgr.c Explicitly enable IPV6_V6ONLY on the netmgr sockets 2022-01-17 22:16:27 +01:00
listenlist.c Update the copyright information in all files in the repository 2022-01-11 09:05:02 +01:00
log.c Update the copyright information in all files in the repository 2022-01-11 09:05:02 +01:00
Makefile.am Remove libns init/shutdown functions 2021-10-04 13:57:34 -07:00
notify.c Update the copyright information in all files in the repository 2022-01-11 09:05:02 +01:00
query.c Fix more ns_statscounter_recursclients underflows 2022-02-23 14:43:09 +01:00
server.c Update the copyright information in all files in the repository 2022-01-11 09:05:02 +01:00
sortlist.c Update the copyright information in all files in the repository 2022-01-11 09:05:02 +01:00
stats.c Update the copyright information in all files in the repository 2022-01-11 09:05:02 +01:00
update.c allow dns_clientinfo to store client ECS data 2022-01-27 14:51:11 -08:00
xfrout.c Reimplement the max-transfer-time-out and max-transfer-idle-out 2022-02-17 22:29:29 +01:00