Compare commits

...
Author SHA1 Message Date
Yorgos Thessalonikefs 970e7db1a0 - Better wording. 2026-10-20 12:41:46 +02:00
Yorgos Thessalonikefs 3ed72c7681 - Fix #1535: [FR] refuse validator configuration without any trust anchor.
Better documentation and warning message.
2026-10-19 17:44:19 +02:00
W.C.A. Wijngaards 440d58045e Changelog note for #1532
- Merge #1532 from Ar-maan05: Fix packet position after a
  short RRSIG in pkt_rrsig_covered.
2026-10-19 10:54:56 +02:00
Armaan SandhuandGitHub e3a0ce98c4 Fix packet position after a short RRSIG in pkt_rrsig_covered (#1532)
pkt_rrsig_covered() moves the buffer position to the RRSIG's TTL and restores it before returning, except on the first early return, when fewer than 25 bytes are left. When it is called from rrset_has_sigover() on an earlier RRSIG while a later RR is being parsed, the parser then continues from the old RRSIG instead of the current RR, and that RR gets the RRSIG's TTL and rdata. Restore the position on that return too.
2026-10-19 10:54:13 +02:00
W.C.A. Wijngaards c5de558e04 - Merge #1531 from nshopik: Fix dnstap queue registration race
between worker threads.
2026-10-19 09:39:13 +02:00
Nikolay ShopikandGitHub be5d1e967a - Fix dnstap queue registration race between worker threads. (#1531)
Workers push their message queue onto dtio->io_list from their own
threads at startup, with no lock, while the io thread may already walk
the list. Two concurrent pushes can lose a queue: the io thread never
drains it, and once its 1 MiB fills, every dnstap message from that
worker is dropped silently until restart.
2026-10-19 09:38:24 +02:00
W.C.A. Wijngaards 6cd9955385 Changelog note for #1528.
- Merge #1528 from Ar-maan05: Fix NSEC at apex detection for
  short type bitmaps.
2026-10-19 09:22:47 +02:00
Armaan SandhuandGitHub aa7634afeb Fix NSEC at apex detection for short type bitmaps (#1528)
nsec_at_apex() starts at the TTL, so the rdata ends at pos + 6 +
rdatalen (4 bytes TTL, 2 bytes rdlength), but both bounds checks use
pos + 4 + rdatalen.  An NSEC whose type bitmap is 3 or 4 bytes long
is then treated as malformed and not flagged as being at the apex,
even when the SOA bit is set.  Use the correct end of the rdata.
2026-10-19 09:21:51 +02:00
7 changed files with 51 additions and 13 deletions
+19 -2
View File
@@ -307,6 +307,11 @@ struct dt_io_thread* dt_io_thread_create(void)
lock_basic_init(&dtio->wakeup_timer_lock); lock_basic_init(&dtio->wakeup_timer_lock);
lock_protect(&dtio->wakeup_timer_lock, &dtio->wakeup_timer_enabled, lock_protect(&dtio->wakeup_timer_lock, &dtio->wakeup_timer_enabled,
sizeof(dtio->wakeup_timer_enabled)); sizeof(dtio->wakeup_timer_enabled));
lock_basic_init(&dtio->io_list_lock);
lock_protect(&dtio->io_list_lock, &dtio->io_list,
sizeof(dtio->io_list));
lock_protect(&dtio->io_list_lock, &dtio->io_list_iter,
sizeof(dtio->io_list_iter));
return dtio; return dtio;
} }
@@ -315,6 +320,7 @@ void dt_io_thread_delete(struct dt_io_thread* dtio)
struct dt_io_list_item* item, *nextitem; struct dt_io_list_item* item, *nextitem;
if(!dtio) return; if(!dtio) return;
lock_basic_destroy(&dtio->wakeup_timer_lock); lock_basic_destroy(&dtio->wakeup_timer_lock);
lock_basic_destroy(&dtio->io_list_lock);
item=dtio->io_list; item=dtio->io_list;
while(item) { while(item) {
nextitem = item->next; nextitem = item->next;
@@ -463,9 +469,11 @@ int dt_io_thread_register_queue(struct dt_io_thread* dtio,
mq->dtio = dtio; mq->dtio = dtio;
lock_basic_unlock(&mq->lock); lock_basic_unlock(&mq->lock);
item->queue = mq; item->queue = mq;
lock_basic_lock(&dtio->io_list_lock);
item->next = dtio->io_list; item->next = dtio->io_list;
dtio->io_list = item; dtio->io_list = item;
dtio->io_list_iter = NULL; dtio->io_list_iter = NULL;
lock_basic_unlock(&dtio->io_list_lock);
return 1; return 1;
} }
@@ -474,6 +482,7 @@ void dt_io_thread_unregister_queue(struct dt_io_thread* dtio,
{ {
struct dt_io_list_item* item, *prev=NULL; struct dt_io_list_item* item, *prev=NULL;
if(!dtio) return; if(!dtio) return;
lock_basic_lock(&dtio->io_list_lock);
item = dtio->io_list; item = dtio->io_list;
while(item) { while(item) {
if(item->queue == mq) { if(item->queue == mq) {
@@ -486,11 +495,13 @@ void dt_io_thread_unregister_queue(struct dt_io_thread* dtio,
lock_basic_unlock(&item->queue->lock); lock_basic_unlock(&item->queue->lock);
free(item); free(item);
dtio->io_list_iter = NULL; dtio->io_list_iter = NULL;
lock_basic_unlock(&dtio->io_list_lock);
return; return;
} }
prev = item; prev = item;
item = item->next; item = item->next;
} }
lock_basic_unlock(&dtio->io_list_lock);
} }
/** pick a message from the queue, the routine locks and unlocks, /** pick a message from the queue, the routine locks and unlocks,
@@ -537,6 +548,7 @@ static int dtio_find_msg(struct dt_io_thread* dtio)
{ {
struct dt_io_list_item *spot, *item; struct dt_io_list_item *spot, *item;
lock_basic_lock(&dtio->io_list_lock);
spot = dtio->io_list_iter; spot = dtio->io_list_iter;
/* use the next queue for the next message lookup, /* use the next queue for the next message lookup,
* if we hit the end(NULL) the NULL restarts the iter at start. */ * if we hit the end(NULL) the NULL restarts the iter at start. */
@@ -548,17 +560,22 @@ static int dtio_find_msg(struct dt_io_thread* dtio)
/* scan from spot to end-of-io_list */ /* scan from spot to end-of-io_list */
item = spot; item = spot;
while(item) { while(item) {
if(dtio_find_in_queue(dtio, item->queue)) if(dtio_find_in_queue(dtio, item->queue)) {
lock_basic_unlock(&dtio->io_list_lock);
return 1; return 1;
}
item = item->next; item = item->next;
} }
/* scan starting at the start-of-list (to wrap around the end) */ /* scan starting at the start-of-list (to wrap around the end) */
item = dtio->io_list; item = dtio->io_list;
while(item) { while(item) {
if(dtio_find_in_queue(dtio, item->queue)) if(dtio_find_in_queue(dtio, item->queue)) {
lock_basic_unlock(&dtio->io_list_lock);
return 1; return 1;
}
item = item->next; item = item->next;
} }
lock_basic_unlock(&dtio->io_list_lock);
return 0; return 0;
} }
+2
View File
@@ -123,6 +123,8 @@ struct dt_io_thread {
int threadnum; int threadnum;
/** event base, for event handling */ /** event base, for event handling */
void* event_base; void* event_base;
/** lock on io_list and io_list_iter */
lock_basic_type io_list_lock;
/** list of queues that is registered to get written */ /** list of queues that is registered to get written */
struct dt_io_list_item* io_list; struct dt_io_list_item* io_list;
/** iterator point in the io_list, to pick from them in a /** iterator point in the io_list, to pick from them in a
+8
View File
@@ -1,3 +1,11 @@
19 October 2026: Wouter
- Merge #1528 from Ar-maan05: Fix NSEC at apex detection for
short type bitmaps.
- Merge #1531 from nshopik: Fix dnstap queue registration race
between worker threads.
- Merge #1532 from Ar-maan05: Fix packet position after a
short RRSIG in pkt_rrsig_covered.
16 October 2026: Wouter 16 October 2026: Wouter
- Fix unit test for root_zonemd with updated root key. - Fix unit test for root_zonemd with updated root key.
+1
View File
@@ -672,6 +672,7 @@ server:
# most modules have to be listed at the beginning of the line, # most modules have to be listed at the beginning of the line,
# except cachedb(just before iterator), and python (at the beginning, # except cachedb(just before iterator), and python (at the beginning,
# or, just before the iterator). # or, just before the iterator).
# Note that validator needs configured trust-anchors to be of any use.
# module-config: "validator iterator" # module-config: "validator iterator"
# File with trusted keys, kept up-to-date using RFC5011 probes, # File with trusted keys, kept up-to-date using RFC5011 probes,
+4 -3
View File
@@ -2171,11 +2171,12 @@ These options are part of the ``server:`` section.
The ordering of the modules is significant, the order decides the order The ordering of the modules is significant, the order decides the order
of processing. of processing.
Setting this to just "iterator" will result in a non-validating server. Setting this to just ``"iterator"`` results in a non-validating server.
Setting this to "validator iterator" will turn on DNSSEC validation. Setting this to ``"validator iterator"`` (default) enables the DNSSEC
validator module but not DNSSEC validation.
.. note:: .. note::
You must also set trust-anchors for validation to be useful. To turn on DNSSEC validation you must configure trust-anchors.
Adding ``respip`` to the front will cause RPZ processing to be done on all Adding ``respip`` to the front will cause RPZ processing to be done on all
queries. queries.
+5 -3
View File
@@ -134,11 +134,11 @@ nsec_at_apex(sldns_buffer* pkt)
} }
/* see if SOA bit is set. */ /* see if SOA bit is set. */
if(sldns_buffer_position(pkt) < pos+4+rdatalen) { if(sldns_buffer_position(pkt) < pos+6+rdatalen) {
/* nsec type bitmap contains items */ /* nsec type bitmap contains items */
uint8_t win, blen, bits; uint8_t win, blen, bits;
/* need: windownum, bitmap len, firstbyte */ /* need: windownum, bitmap len, firstbyte */
if(sldns_buffer_position(pkt)+3 > pos+4+rdatalen) { if(sldns_buffer_position(pkt)+3 > pos+6+rdatalen) {
sldns_buffer_set_position(pkt, pos); sldns_buffer_set_position(pkt, pos);
return 0; /* malformed nsec */ return 0; /* malformed nsec */
} }
@@ -246,8 +246,10 @@ pkt_rrsig_covered(sldns_buffer* pkt, uint8_t* here, uint16_t* type)
size_t pos = sldns_buffer_position(pkt); size_t pos = sldns_buffer_position(pkt);
sldns_buffer_set_position(pkt, (size_t)(here-sldns_buffer_begin(pkt))); sldns_buffer_set_position(pkt, (size_t)(here-sldns_buffer_begin(pkt)));
/* ttl + len + size of small rrsig(rootlabel, no signature) */ /* ttl + len + size of small rrsig(rootlabel, no signature) */
if(sldns_buffer_remaining(pkt) < 4+2+19) if(sldns_buffer_remaining(pkt) < 4+2+19) {
sldns_buffer_set_position(pkt, pos);
return 0; return 0;
}
sldns_buffer_skip(pkt, 4); /* ttl */ sldns_buffer_skip(pkt, 4); /* ttl */
if(sldns_buffer_read_u16(pkt) < 19) /* too short */ { if(sldns_buffer_read_u16(pkt) < 19) /* too short */ {
sldns_buffer_set_position(pkt, pos); sldns_buffer_set_position(pkt, pos);
+12 -5
View File
@@ -231,6 +231,7 @@ val_init(struct module_env* env, int id)
{ {
struct val_env* val_env = (struct val_env*)calloc(1, struct val_env* val_env = (struct val_env*)calloc(1,
sizeof(struct val_env)); sizeof(struct val_env));
struct trust_anchor* anchor = NULL;
if(!val_env) { if(!val_env) {
log_err("malloc failure"); log_err("malloc failure");
return 0; return 0;
@@ -247,16 +248,22 @@ val_init(struct module_env* env, int id)
log_err("validator: could not apply configuration settings."); log_err("validator: could not apply configuration settings.");
return 0; return 0;
} }
if(env->cfg->disable_edns_do) {
struct trust_anchor* anchor = anchors_find_any_noninsecure( anchor = anchors_find_any_noninsecure(env->anchors);
env->anchors); if(anchor) {
if(anchor) { if(env->cfg->disable_edns_do) {
char b[LDNS_MAX_DOMAINLEN]; char b[LDNS_MAX_DOMAINLEN];
dname_str(anchor->name, b); dname_str(anchor->name, b);
log_warn("validator: disable-edns-do is enabled, but there is a trust anchor for '%s'. Since DNSSEC could not work, the disable-edns-do setting is turned off. Continuing without it.", b); log_warn("validator: disable-edns-do is enabled, but there is a trust anchor for '%s'. Since DNSSEC could not work, the disable-edns-do setting is turned off. Continuing without it.", b);
lock_basic_unlock(&anchor->lock);
env->cfg->disable_edns_do = 0; env->cfg->disable_edns_do = 0;
} }
lock_basic_unlock(&anchor->lock);
} else {
log_warn("validator: no DNSSEC trust anchors configured. "
"DNSSEC validation is now effectively DISABLED. "
"Either configure a trust anchor to enable DNSSEC "
"validation or remove the validator from "
"module-config.");
} }
return 1; return 1;