Commit graph

464 commits

Author SHA1 Message Date
Evan Hunt
134706912f
Disable UPDATE and NOTIFY for non-IN classes
Return NOTIMP for UPDATE and NOTIFY requests received for views with a
class other than IN.  Only QUERY is now supported for non-IN views such
as CHAOS.

When running dns dns_rdata_tostruct() with types that are only defined
for class IN, ensure that the class is correct before proceeding.

Add an assertion that any zone being updated is of class IN. (Note
that previously, a DLZ zone could have its class value set incorrectly
to NONE; this has been fixed.)

This addresses YWH-PGM40640-70 and YWH-PGM40640-73 (as well as any
similar problems that might have occurred in the future) by minimizing
the code paths that can be reached by rdata classes other than IN, so it
is safe for the implementation to assume that rdatatypes that are only
defined for class IN, such as SVCB or WKS, have been parsed and
validated, and not accepted as unknown/opaque data.

Fixes: isc-projects/bind9#5777
Fixes: isc-projects/bind9#5779

(cherry picked from commit a6d8e330ed6cf0021bff3f00aa1dc7a296f5aec0)
2026-05-07 13:09:18 +02:00
Colin Vidal
1bedd7f244
Limit the number of addresses returned per ADB find
Add a hard limit on the number of addresses that ADB returns from a
single NS lookup (dns_adbfind_t).  This mitigates a flood attack
where an attacker controls a zone with many addresses for a
nameserver, each returning an invalid response.  The global
max-query count (default 50) also limits this, but significant harm
can be done before that limit is reached.

The default limit is now 6 (v4 and/or v6) addresses for an ADB find (so,
ADB looking up for A/AAAA addresses of a name server name). It can be
overridden for testing via 'named -T adbaddrslimit=N'.

(cherry picked from commit 3ec37fc69356ee682bee7f67940613ac31d93d7b)
2026-05-07 13:09:18 +02:00
Ondřej Surý
fb8a9e73cc Fix non-atomic read-modify-write on entry->srtt in adjustsrtt()
The SRTT update loaded the old value, computed a new one, and stored it
back as separate operations.  Two concurrent callers could each read the
same old value and one update would be silently lost.

Use a CAS loop for the read-modify-write on entry->srtt.  For the aging
path, also CAS on entry->lastage to prevent multiple threads from aging
the same entry in the same second.

(cherry picked from commit 4d15494b94)
2026-03-20 01:06:56 +00:00
Michal Nowak
82991c7881
Use clang-format-22 to update formatting
(cherry picked from commit 239464f276)
2026-03-04 12:18:27 +01:00
Colin Vidal
60ae2c67e3 fetch loop detection improvements
The fetch loop detection occured in two places: when
`dns_resolver_createfetch()` is invoked (looking up through the parent
fetches chain and stops the fetch if a parent fetch is the same qname and
qtype) and right after calling `dns_adb_findname()` in the resolver
(stops the fetch if the current fetch is the same name from the ADB
lookup, and ADB lookup needs to fetch it).

Regarding fetch loop detection at the `dns_resulver_createfetch()`
entry, there are case where both qname and qtype are similar but the
zonecut is different. This will then query different name servers and
get different responses. For instance, the following delegation
parent-side (both for `foo.example.` and `dnshost.example.`):

	foo.example.		3600	NS	ns.dnshost.example.
	dnshost.example.	3600	NS	ns.dnshost.example.
	ns.dnshost.example.	3600	A	1.2.3.4

Then the child-side of `dnshost.example.`:

	dnshost.example.	300	NS	ns.dnshost.example.
	ns.dnshost.example.	300	A	1.2.3.4

Then the child-side of `foo.example.`:

	foo.example		3600	NS	ns.dnshost.example.
	a.foo.example		300	A	5.6.7.8

Obviously, there is a misconfiguration between the parent-side and the
child-side of `dnshost.example` (the mismatch of the TTL), but, this
happens...

Because the resolver is currently child-centric, the parent-side
delegation's glue of `dnshost.example.` will be overriden by the
child-side of the delegation. Once both A records will expires, the
resolver will attempt to find out the A RRs but will start from the
`foo.example.` zonecut, as the delegation itself is still valid.

Then the resolver will attempt to resolve `ns.dnshost.example.`, still
using the `foo.example.` zonecut, which will immediately trigger another
attempt to resolve `ns.foo.example.` (because the A RR is expired). This
is, however _not_ a loop, because the second attempt will have
`dnshost.example.` zonecut.  And this changes everything, because the
resolver detects the A name is in-domain, and pass a flag to ADB so
`dns_view_find()` won't use the cache. As a result, the zonecut will be
`.`, and the hints (root servers) will be queried instead.

From that point, they'll return the parent-side delegation, which
includes the glue for `ns.dnshost.example/A`, and the resolution can
continue. Previously, this wouldn't be possible because a loop would be
detected from the second attempt to looking `ns.foo.example/A` and would
result in a SERVFAIL.

Now, the loop detection is relaxed as the loop is detected if the qname,
qtype _and_ zonecut are equals.

This commit also changes the way the loop detection post
`dns_adb_createfind()` works. From the same example above, there would
be two ADB fetches with the same name, but with two different ADB flags
(the first one without DNS_ADB_STARTATZONE, the second one with that
flag). It means that there will be two fetches out of those two ADB
lookups, both legit, and not a loop (i.e. it won't be stuck). To
differenciate between a find which has a pending fetch (which could be
from another find the current find has been attached to), a new find
option `DNS_ADBFIND_STARTEDFETCH` is introduced, which tells that the
current has did started a fetch.

That way, if a find doesn't have `DNS_ADBFIND_STARTEDFETCH` option but
has pending fetches, we know this is a find attached to a similar find
so this is a loop. Otherwise, with `DNS_ADBFIND_STARTEDFETCH`, we know
that even if there is a pending fetch, this is not a loop as the fetch
has just been started

(cherry picked from commit f623ab1fb3)
2026-02-20 18:11:29 +01:00
Colin Vidal
ed184d8545 extends named -T so ADB settings can be tweaked
ADB entry window and ADB min cache time can be tweaked using `named -T
adbentrywindow=<unsigned int>` and `named -T adbmincache=<unsigned
int>`.

While those values doesn't needs to be exposed to the operator, this can
be needed to be able to system test ADB behaviors without having to wait
as long as those values are by default.

(cherry picked from commit e5f963262a)
2026-02-20 18:11:29 +01:00
Ondřej Surý
5cd69a3dcf
Detect resolution loops between fetches
Maintain the relationship between the parent and child fetch and when
creating a new child fetch, properly check the resolution loops that
would lead to a new fetch would join one of the parent's fetch contexts.

(cherry picked from commit 4d307ac67a)
2025-11-28 09:32:53 +01:00
Ondřej Surý
822ada5db1 When overmem, clean enough memory when adding new ADB names/entries
The purge_stale_names()/purge_stale_entries() is opportunistic even when
we are under memory pressure (overmem).  Split the opportunistic LRU
cleaning and overmem cleaning.  This makes the stale purging much
simpler as we don't have to try that hard and makes the overmem cleaning
always cleanup double the amount of the newly allocated ADB name/entry.

(cherry picked from commit eb0ffa0d5f)
2025-07-11 13:58:11 +02:00
Mark Andrews
5c0057cc11 Separate out adbname flags that are hashed
There are three adbname flags that are used to identify different
types of adbname lookups when hashing rather than using multiple
hash tables.  Separate these to their own structure element as these
need to be able to be read without locking the adbname structure.

(cherry picked from commit 9158e63218)
2025-07-07 11:10:07 +10:00
Mark Andrews
53738b0e5e Use clang-format-20 to update formatting
(cherry picked from commit 422b9118e8)
2025-06-25 13:32:08 +10:00
Mark Andrews
db113bc5ad Fix gaining adbname reference
Call dns_adbname_ref before calling dns_resolver_createfetch to
ensure adbname->name remains stable for the life of the fetch.

(cherry picked from commit 8e7229f641)
2025-03-21 00:29:45 +00:00
Ondřej Surý
1ffb67a135 Split and simplify the use of EDE list implementation
Instead of mixing the dns_resolver and dns_validator units directly with
the EDE code, split-out the dns_ede functionality into own separate
compilation unit and hide the implementation details behind abstraction.

Additionally, the EDE codes are directly copied into the ns_client
buffers by passing the EDE context to dns_resolver_createfetch().

This makes the dns_ede implementation simpler to use, although sligtly
more complicated on the inside.

Co-authored-by: Colin Vidal <colin@isc.org>
Co-authored-by: Ondřej Surý <ondrej@isc.org>
(cherry picked from commit 2f8e0edf3b)
2025-01-30 12:37:55 +00:00
Ondřej Surý
819e809be5
Remove memory limit on ADB finds and fetches
Address Database (ADB) shares the memory for the short lived ADB
objects (finds, fetches, addrinfo) and the long lived ADB
objects (names, entries, namehooks).  This could lead to a situation
where the resolver-heavy load would force evict ADB objects from the
database to point where ADB is completely empty, leading to even more
resolver-heavy load.

Make the short lived ADB objects use the other memory context that we
already created for the hashmaps.  This makes the ADB overmem condition
to not be triggered by the ongoing resolver fetches.

(cherry picked from commit 05faff6d53)
2025-01-22 15:01:33 +01:00
Matthijs Mekking
492f79560d Implement global limit for outgoing queries
This global limit is not reset on query restarts and is a hard limit
for any client request.

(cherry picked from commit 16b3bd1cc7)
2024-12-06 06:20:33 +00:00
Colin Vidal
c586d9a658 Add EDE 22 No reachable authority code
Add support for Extended DNS Errors (EDE) error 22: No reachable
authority. This occurs when after a timeout delay when the resolver is
trying to query an authority server.

(cherry picked from commit d13e94b930)

Commit amended in order to fix usage of isc_log_write (adding dns_lctx
parameter)
2024-12-05 10:30:28 +01:00
Ondřej Surý
58a15d38c2
Remove redundant parentheses from the return statement
(cherry picked from commit 0258850f20)
2024-11-19 14:26:52 +01:00
Ondřej Surý
d6f2dd79f6 Revalidate the adbname when canceling the ADB find
When canceling the ADB find, the lock on the find gets released for
a brief period of time to be locked again inside adbname lock.  During
the brief period that the ADB find is unlocked, it can get canceled by
other means removing it from the adbname list which in turn causes
assertion failure due to a double removal from the adbname list.

Recheck if the find->adbname is still valid after acquiring the lock
again and if not just skip the double removal.  Additionally, attach to
the adbname as in the worst case, the adbname might also cease to exist
if the scheduler would block this particular thread for a longer period
of time invalidating the lock we are going to acquire and release.

(cherry picked from commit 128e50e1ff)
2024-11-13 07:51:19 +00:00
Mark Andrews
7e8ffe3d63 Store static-stub addresses seperately in the adb
Static-stub address and addresses from other sources where being
mixed together resulting in static-stub queries going to addresses
not specified in the configuration or alternatively static-stub
addresses being used instead of the real addresses.

(cherry picked from commit b3a2c790f3)
2024-10-01 01:27:55 +00:00
Mark Andrews
1be660a1a2 Use atomics to access find->status
(cherry picked from commit a45e39d114)
2024-09-02 03:25:35 +00:00
Mark Andrews
ce6c0c26a0 Use an accessor fuction to access find->status
find->status is marked as private and access is controlled
by find->lock.

(cherry picked from commit c900300f21)
2024-09-02 03:25:35 +00:00
Aram Sargsyan
c90aa16929 Exempt prefetches from the fetches-per-server quota
Give prefetches a free pass through the quota so that the cache
entries for popular zones could be updated successfully even if the
quota for is already reached.

(cherry picked from commit c7e8b7cf63)
2024-08-26 15:54:02 +00:00
Mark Andrews
450aa90309 Do not update find.result_v4 and find.result_v6
These values are supposed to be static for the life of the find and
clean_finds_at_name was updating them resulting in TSAN error
reports.

    WARNING: ThreadSanitizer: data race
    Write of size 4 at 0x000000000001 by thread T1 (mutexes: write M1, write M2):
      #0 clean_finds_at_name lib/dns/adb.c:1537
      #1 fetch_callback lib/dns/adb.c:4009
      #2 task_run lib/isc/task.c:815
      #3 isc_task_run lib/isc/task.c:896
      #4 isc__nm_async_task netmgr/netmgr.c:848
      #5 process_netievent netmgr/netmgr.c:920
      #6 process_queue netmgr/netmgr.c:1013
      #7 process_all_queues netmgr/netmgr.c:767
      #8 async_cb netmgr/netmgr.c:796
      #9 uv__async_io /usr/src/libuv-v1.44.1/src/unix/async.c:163
      #10 isc__trampoline_run lib/isc/trampoline.c:189

    Previous read of size 4 at 0x000000000001 by thread T2:
      #0 findname lib/dns/resolver.c:3749
      #1 fctx_getaddresses lib/dns/resolver.c:3993
      #2 fctx_try lib/dns/resolver.c:4390
      #3 rctx_nextserver lib/dns/resolver.c:10356
      #4 rctx_done lib/dns/resolver.c:10503
      #5 resquery_response lib/dns/resolver.c:8511
      #6 udp_recv lib/dns/dispatch.c:638
      #7 isc__nm_async_readcb netmgr/netmgr.c:2885
      #8 isc__nm_readcb netmgr/netmgr.c:2858
      #9 udp_recv_cb netmgr/udp.c:650
      #10 isc__nm_udp_read_cb netmgr/udp.c:1057
      #11 uv__udp_recvmsg /usr/src/libuv-v1.44.1/src/unix/udp.c:303
      #12 isc__trampoline_run lib/isc/trampoline.c:189

(cherry picked from commit 53a5f50e9d)
2024-07-31 06:20:45 +00:00
Ondřej Surý
141e4c9805
Change the ADB_ENTRY_WINDOW to 60 seconds
The previous value of 30 minutes used to cache the ADB names and entries
was quite long.  Change the value to 60 seconds for faster recovery
after cached intermittent failure of the remote nameservers.
2024-04-22 10:36:36 +02:00
Ondřej Surý
6708da3112
Unify the expiration time handling for all ADB expiration
The algorithm from the previous commit[1] is now used to calculate all
the expiration values through the code (ncache results, cname/dname
targets).

1. ISC_MIN(cur, ISC_MAX(now + ADB_ENTRY_WINDOW, now + rdataset->ttl))
2024-04-22 10:36:36 +02:00
Ondřej Surý
53cc00ee3f
Fix the expire_v4 and expire_v6 logic
Correct the logic to set the expiration period of expire_{v4,v6} as
follows:

1. If the trust is ultimate (local entry), immediately set the entry as
   expired, so the changes to the local zones have immediate effect.

3. If the expiration is already set and smaller than the new value, then
   leave the expiration value as it is.

2. Otherwise pick larger of `now + ADB_ENTRY_WINDOW` and `now + TTL` as
   the new expiration value.
2024-04-22 10:36:36 +02:00
Ondřej Surý
932665410d
Always set ADB entry expiration to now + ADB_ENTRY_WINDOW
When ADB entry was created it was set to never expire.  If we never
called any of the functions that adjust the expiration, it could linger
in the ADB forever.

Set the expiration (.expires) to now + ADB_ENTRY_WINDOW when creating
the new ADB entry to ensure the ADB entry will always expire.
2024-04-22 10:36:36 +02:00
Evan Hunt
c47fa689d4
use a thread-local variable to get the current running loop
if we had a method to get the running loop, similar to how
isc_tid() gets the current thread ID, we can simplify loop
and loopmgr initialization.

remove most uses of isc_loop_current() in favor of isc_loop().
in some places where that was the only reason to pass loopmgr,
remove loopmgr from the function parameters.
2024-04-02 10:35:56 +02:00
Ondřej Surý
14bdd21e0a
Refactor the handling of isc_mem overmem condition
Previously, there were two methods of working with the overmem
condition:

1. hi/lo water callback - when the overmem condition was reached
   for the first time, the water callback was called with HIWATER
   mark and .is_overmem boolean was set internally.  Similarly,
   when the used memory went below the lo water mark, the water
   callback would be called with LOWATER mark and .is_overmem
   was reset.  This check would be called **every** time memory
   was allocated or freed.

2. isc_mem_isovermem() - a simple getter for the internal
   .is_overmem flag

This commit refactors removes the first method and move the hi/lo water
checks to the isc_mem_isovermem() function, thus we now have only a
single method of checking overmem condition and the check for hi/lo
water is removed from the hot path for memory contexts that doesn't use
overmem checks.
2023-11-29 14:16:20 +01:00
Mark Andrews
9227b82e71 Also look for additional records in dns_adb_find
If a child zone is served by the same servers as a parent zone and
a NS query is made for the zone name then the addresses of the
nameservers are returned in the additional section are tagged as
trust additional.
2023-11-01 16:49:08 +01:00
Mark Andrews
578da93581 Turn on QNAME minimisation when fetching nameserver addresses 2023-11-01 16:49:08 +01:00
Michal Nowak
dd234c60fe
Update the source code formatting using clang-format-17 2023-10-17 17:47:46 +02:00
Ondřej Surý
91f3b0edee
Use mul and div instead of bitshifts to calculate srtt
There was a microoptimization for smoothing srtt with bitshifts.  Revert
the code to use * 98 / 100, it doesn't really make that difference on
modern CPUs, for comparison here:

    muldiv:
	    imul    eax, edi, 98
	    imul    rax, rax, 1374389535
	    shr     rax, 37
	    ret
    shift:
	    mov     eax, edi
	    sal     eax, 9
	    sub     eax, edi
	    shr     eax, 9
	    ret
2023-10-12 12:35:00 +02:00
Ondřej Surý
0635bd01cb
Skip the no-op code in adjustsrtt()
If factor == DNS_ADB_RTTADJAGE and addr->entry->lastage == now we would
load value into new_srtt and then immediatelly store it back which
triggers the synchronization between threads using .srtt values.
2023-10-12 12:35:00 +02:00
Ondřej Surý
cb0db600e7
Replace some ADB entry locking with atomics to reduce ADB contention
Use atomics on couple of ADB entry members (.srtt, .flags, .expires, and
.lastage) to remove ADB entry locking from couple of hot spots.  The
most prominent place is copy_namehook_lists() that gets called under ADB
name lock and if the namehook list is long it acquires-releases quite a
few ADB entry locks.  Changing those ADB entry members to atomics
allowed us to new_adbaddrinfo() not require locked ADB entry and since
adbentry_overquota() already used atomics and handling lame information
was dropped in the previous commit, we could not make the
copy_namehook_lists() lockless.

The other hotspot is dns_adb_adjustsrtt() and dns_adb_agesrtt() that can
now use atomics because .srtt is already atomic_uint.

And the last place that could now use atomics is dns_adb_changeflags().
2023-10-12 12:35:00 +02:00
Ondřej Surý
2b20db05e3
Remove dns_adblameinfo from dns_adb
Keeping the information about lame server in the ADB was done in !322 to
fix following security issue:

    [CVE-2021-25219] Disable "lame-ttl" cache

The handling of the lame servers needs to be redesigned and it is not
going to be enabled any time soon, and the current code is just dead
code that takes up space, code and stands in the way of making ADB work
faster.

Remove all the internals needed for handling the lame servers in the ADB
for now.  It might get reintroduced later if and when we redesign ADB.
2023-10-12 12:35:00 +02:00
Ondřej Surý
3340c82b99
Improve isc_refcount with initializer and implicit destroy
Add ISC_REFCOUNT_INITIALIZER(x) macro and implicitly call
isc_refcount_destroy() in the ISC_REFCOUNT_IMPL() macros
to reduce code duplicities.
2023-09-24 10:08:56 +02:00
Ondřej Surý
e270266627
Refactor isc_hashmap to accept custom match function
Refactor isc_hashmap to allow custom matching functions.  This allows us
to have better tailored keys that don't require fixed uint8_t arrays,
but can be composed of more fields from the stored data structure.
2023-09-16 07:20:48 +02:00
Tony Finch
c622b349e4
Apply the SET_IF_NOT_NULL() semantic patch
spatch --sp-file cocci/set_if_not_null.spatch --use-gitgrep --dir "." --include-headers --in-place
2023-08-15 12:21:41 +02:00
Ondřej Surý
045d8d9ed6 Refactor dns_adb_create() to return void
After isc_stats_create() change, the dns_adb_create() cannot fail, so
refactor the function to return void and fix all its uses.
2023-07-27 11:37:44 +02:00
Ondřej Surý
5321c474ea Refactor isc_stats_create() and its downstream users to return void
The isc_stats_create() can no longer return anything else than
ISC_R_SUCCESS.  Refactor isc_stats_create() and its variants in libdns,
libns and named to just return void.
2023-07-27 11:37:44 +02:00
Evan Hunt
0955cf1af5 clean up numbering of FETCHOPT and ADDRINFO flags
in the past there was overlap between the fields used
as resolver fetch options and ADB addrinfo flags. this has
mostly been eliminated; now we can clean up the rest of
it and remove some confusing comments.
2023-07-04 18:23:57 +00:00
Ondřej Surý
b8d34e960b
Change dns_adbentry_overquota() to dns_adb_overquota()
The dns_adbentry_overquota() was violating the layers accessing the
adbentry struct members directly.  Change it to dns_adb_overquota() to
match the dns_adb API.
2023-04-04 16:21:49 +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ý
668d287d01
Don't remove ADB entry from LRU before trying to expire it
There was a code flow error that would remove the expired ADB entry from
the LRU list and then a check in the expire_entry() would cause
assertion error because it expect the ADB entry to be linked.

Additionally, the expire mechanism would loop for cases when we would
held only a read rwlock; in such case we need to upgrade the lock and
try again, not just try again.
2023-02-17 07:16:50 +01:00
Evan Hunt
a52b17d39b
remove isc_task completely
as there is no further use of isc_task in BIND, this commit removes
it, along with isc_taskmgr, isc_event, and all other related types.

functions that accepted taskmgr as a parameter have been cleaned up.
as a result of this change, some functions can no longer fail, so
they've been changed to type void, and their callers have been
updated accordingly.

the tasks table has been removed from the statistics channel and
the stats version has been updated. dns_dyndbctx has been changed
to reference the loopmgr instead of taskmgr, and DNS_DYNDB_VERSION
has been udpated as well.
2023-02-16 18:35:32 +01:00
Evan Hunt
0312789129
refactor dns_resolver to use loop callbacks
callback events from dns_resolver_createfetch() are now posted
using isc_async_run.

other modules which called the resolver and maintained task/taskmgr
objects for this purpose have been cleaned up.
2023-02-16 17:27:59 +01:00
Evan Hunt
31aee2ef9c
refactor dns_adb to use loop callbacks
The callbacks from dns_abd_createfind() are now posted using
isc_async_run() instead of isc_task_send().  ADB event types
have been replaced with a new dns_adbstatus_t type which is
included as find->status.

(The ADB still uses a task for dns_resolver_createfetch().)
2023-02-16 14:55:06 +01:00
Tony Finch
6927a30926 Remove do-nothing header <isc/print.h>
This one really truly did nothing. No lines added!
2023-02-15 16:44:47 +00:00
Ondřej Surý
c194ff5d77
Use C-RW-WP lock in the dns_adb unit
Replace the isc_mutex in the dns_adb unit with isc_rwlock for better
performance.  Both ADB names and ADB entries hashtables and LRU are now
using isc_rwlock.
2023-02-15 09:30:04 +01:00
Ondřej Surý
3cda9f9f14 Properly name ADB hashmap and named log memory contexts
The ADB hashmaps are stored in extra memory contexts, so the hash
tables are excluded from the overmem accounting.  The new memory
context was unnamed, give it a proper name.

Same thing has happened with extra memory context used for named
global log context - give the extra memory context a proper name.
2023-01-30 11:52:53 +01:00