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

fix: usr: Fix a bug in the static-stub implementation

Static-stub addresses and addresses from other sources were 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 correct server addresses.

Closes #4850

Merge branch '4850-add-an-additional-class-of-names-to-adb' into 'main'

See merge request isc-projects/bind9!9314
This commit is contained in:
Mark Andrews
2024-10-01 01:26:56 +00:00
5 changed files with 62 additions and 25 deletions

View File

@@ -265,7 +265,7 @@ ISC_REFCOUNT_DECL(dns_adbentry);
* Internal functions (and prototypes).
*/
static dns_adbname_t *
new_adbname(dns_adb_t *adb, const dns_name_t *, bool start_at_zone);
new_adbname(dns_adb_t *adb, const dns_name_t *, unsigned int flags);
static void
destroy_adbname(dns_adbname_t *);
static bool
@@ -296,7 +296,7 @@ static void
purge_stale_names(dns_adb_t *adb, isc_stdtime_t now);
static dns_adbname_t *
get_attached_and_locked_name(dns_adb_t *, const dns_name_t *,
bool start_at_zone, isc_stdtime_t now);
unsigned int flags, isc_stdtime_t now);
static void
purge_stale_entries(dns_adb_t *adb, isc_stdtime_t now);
static dns_adbentry_t *
@@ -409,9 +409,12 @@ enum {
#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) != 0)
#define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) != 0)
#define FIND_STATICSTUB(fn) (((fn)->options & DNS_ADBFIND_STATICSTUB) != 0)
#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
#define FIND_NOFETCH(fn) (((fn)->options & DNS_ADBFIND_NOFETCH) != 0)
#define ADBNAME_FLAGS_MASK (DNS_ADBFIND_STARTATZONE | DNS_ADBFIND_STATICSTUB)
/*
* These are currently used on simple unsigned ints, so they are
* not really associated with any particular type.
@@ -951,7 +954,7 @@ clean_finds_at_name(dns_adbname_t *name, dns_adbstatus_t astat,
}
static dns_adbname_t *
new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, bool start_at_zone) {
new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, unsigned int flags) {
dns_adbname_t *name = NULL;
name = isc_mem_get(adb->mctx, sizeof(*name));
@@ -966,6 +969,7 @@ new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, bool start_at_zone) {
.v6 = ISC_LIST_INITIALIZER,
.finds = ISC_LIST_INITIALIZER,
.link = ISC_LINK_INITIALIZER,
.flags = flags & ADBNAME_FLAGS_MASK,
.magic = DNS_ADBNAME_MAGIC,
};
@@ -981,10 +985,6 @@ new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, bool start_at_zone) {
dns_name_copy(dnsname, name->name);
dns_name_init(&name->target, NULL);
if (start_at_zone) {
name->flags |= DNS_ADBFIND_STARTATZONE;
}
inc_adbstats(adb, dns_adbstats_namescnt);
return (name);
}
@@ -1235,8 +1235,8 @@ match_adbname(void *node, const void *key) {
const dns_adbname_t *adbname0 = node;
const dns_adbname_t *adbname1 = key;
if ((adbname0->flags & DNS_ADBFIND_STARTATZONE) !=
(adbname1->flags & DNS_ADBFIND_STARTATZONE))
if ((adbname0->flags & ADBNAME_FLAGS_MASK) !=
(adbname1->flags & ADBNAME_FLAGS_MASK))
{
return (false);
}
@@ -1247,12 +1247,12 @@ match_adbname(void *node, const void *key) {
static uint32_t
hash_adbname(const dns_adbname_t *adbname) {
isc_hash32_t hash;
bool start_at_zone = adbname->flags & DNS_ADBFIND_STARTATZONE;
unsigned int flags = adbname->flags & ADBNAME_FLAGS_MASK;
isc_hash32_init(&hash);
isc_hash32_hash(&hash, adbname->name->ndata, adbname->name->length,
false);
isc_hash32_hash(&hash, &start_at_zone, sizeof(start_at_zone), true);
isc_hash32_hash(&hash, &flags, sizeof(flags), true);
return (isc_hash32_finalize(&hash));
}
@@ -1261,14 +1261,14 @@ hash_adbname(const dns_adbname_t *adbname) {
*/
static dns_adbname_t *
get_attached_and_locked_name(dns_adb_t *adb, const dns_name_t *name,
bool start_at_zone, isc_stdtime_t now) {
unsigned int flags, isc_stdtime_t now) {
isc_result_t result;
dns_adbname_t *adbname = NULL;
isc_time_t timenow;
isc_stdtime_t last_update;
dns_adbname_t key = {
.name = UNCONST(name),
.flags = (start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0,
.flags = flags & ADBNAME_FLAGS_MASK,
};
uint32_t hashval = hash_adbname(&key);
isc_rwlocktype_t locktype = isc_rwlocktype_read;
@@ -1294,7 +1294,7 @@ get_attached_and_locked_name(dns_adb_t *adb, const dns_name_t *name,
UPGRADELOCK(&adb->names_lock, locktype);
/* Allocate a new name and add it to the hash table. */
adbname = new_adbname(adb, name, start_at_zone);
adbname = new_adbname(adb, name, key.flags);
void *found = NULL;
result = isc_hashmap_add(adb->names, hashval, match_adbname,
@@ -1959,6 +1959,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
now = isc_stdtime_now();
}
/*
* If STATICSTUB is set we always want to have STARTATZONE set.
*/
if (options & DNS_ADBFIND_STATICSTUB) {
options |= DNS_ADBFIND_STARTATZONE;
}
/*
* Remember what types of addresses we are interested in.
*/
@@ -1975,8 +1982,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
again:
/* Try to see if we know anything about this name at all. */
adbname = get_attached_and_locked_name(adb, name,
FIND_STARTATZONE(find), now);
adbname = get_attached_and_locked_name(adb, name, find->options, now);
if (NAME_DEAD(adbname)) {
UNLOCK(&adbname->lock);
@@ -2050,7 +2056,7 @@ again:
* Any other result, start a fetch for A, then fall
* through to AAAA.
*/
if (!NAME_FETCH_A(adbname)) {
if (!NAME_FETCH_A(adbname) && !FIND_STATICSTUB(find)) {
wanted_fetches |= DNS_ADBFIND_INET;
}
break;
@@ -2093,7 +2099,8 @@ again:
/*
* Any other result, start a fetch for AAAA.
*/
if (!NAME_FETCH_AAAA(adbname)) {
if (!NAME_FETCH_AAAA(adbname) && !FIND_STATICSTUB(find))
{
wanted_fetches |= DNS_ADBFIND_INET6;
}
break;
@@ -3391,6 +3398,7 @@ dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) {
dns_adbname_t *adbname = NULL;
isc_result_t result;
bool start_at_zone = false;
bool static_stub = false;
dns_adbname_t key = { .name = UNCONST(name) };
REQUIRE(DNS_ADB_VALID(adb));
@@ -3403,9 +3411,11 @@ dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) {
RWLOCK(&adb->names_lock, isc_rwlocktype_write);
again:
/*
* Delete both entries - without and with DNS_ADBFIND_STARTATZONE set.
* Delete all entries - with and without DNS_ADBFIND_STARTATZONE set
* and with and without DNS_ADBFIND_STATICSTUB set.
*/
key.flags = (start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0;
key.flags = ((static_stub) ? DNS_ADBFIND_STATICSTUB : 0) |
((start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0);
result = isc_hashmap_find(adb->names, hash_adbname(&key), match_adbname,
(void *)&key, (void **)&adbname);
@@ -3422,6 +3432,10 @@ again:
start_at_zone = true;
goto again;
}
if (!static_stub) {
static_stub = true;
goto again;
}
RWUNLOCK(&adb->names_lock, isc_rwlocktype_write);
}

View File

@@ -192,6 +192,10 @@ struct dns_adbfind {
* Don't perform a fetch even if there are no address records available.
*/
#define DNS_ADBFIND_NOFETCH 0x00000800
/*%
* Only look for glue record for static stub.
*/
#define DNS_ADBFIND_STATICSTUB 0x00001000
/*%
* The answers to queries come back as a list of these.

View File

@@ -265,6 +265,7 @@ struct dns_rdataset {
#define DNS_RDATASETATTR_STALE_WINDOW 0x04000000
#define DNS_RDATASETATTR_STALE_ADDED 0x08000000
#define DNS_RDATASETATTR_KEEPCASE 0x10000000
#define DNS_RDATASETATTR_STATICSTUB 0x20000000
/*%
* _OMITDNSSEC:

View File

@@ -627,8 +627,9 @@ enum {
#define BADCOOKIE(a) (((a)->flags & FCTX_ADDRINFO_BADCOOKIE) != 0)
#define ISDUALSTACK(a) (((a)->flags & FCTX_ADDRINFO_DUALSTACK) != 0)
#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
#define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
#define STATICSTUB(r) (((r)->attributes & DNS_RDATASETATTR_STATICSTUB) != 0)
#ifdef ENABLE_AFL
bool dns_fuzzing_resolver = false;
@@ -3596,6 +3597,7 @@ normal_nses:
result = dns_rdataset_next(&fctx->nameservers))
{
bool overquota = false;
unsigned int static_stub = 0;
dns_rdataset_current(&fctx->nameservers, &rdata);
/*
@@ -3606,13 +3608,19 @@ normal_nses:
continue;
}
if (STATICSTUB(&fctx->nameservers) &&
dns_name_equal(&ns.name, fctx->domain))
{
static_stub = DNS_ADBFIND_STATICSTUB;
}
if (no_addresses > NS_FAIL_LIMIT &&
dns_rdataset_count(&fctx->nameservers) > NS_RR_LIMIT)
{
stdoptions |= DNS_ADBFIND_NOFETCH;
}
findname(fctx, &ns.name, 0, stdoptions, 0, now, &overquota,
&need_alternate, &no_addresses);
findname(fctx, &ns.name, 0, stdoptions | static_stub, 0, now,
&overquota, &need_alternate, &no_addresses);
if (!overquota) {
all_spilled = false;

View File

@@ -930,7 +930,9 @@ db_find:
result = ISC_R_SUCCESS;
}
if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
if (result == ISC_R_NOTFOUND && !is_staticstub_zone && use_hints &&
view->hints != NULL)
{
if (dns_rdataset_isassociated(rdataset)) {
dns_rdataset_disassociate(rdataset);
}
@@ -1145,6 +1147,14 @@ db_find:
goto cleanup;
}
/*
* Tag static stub NS RRset so that when we look for
* addresses we use the configured server addresses.
*/
if (dns_zone_gettype(zone) == dns_zone_staticstub) {
rdataset->attributes |= DNS_RDATASETATTR_STATICSTUB;
}
if (use_cache && view->cachedb != NULL && db != view->hints) {
/*
* We found an answer, but the cache may be better.