Compare commits

...
Author SHA1 Message Date
W.C.A. Wijngaards c3a3182edd - checkconf-zone-check, documentation in the man page. 2026-10-19 16:22:28 +02:00
W.C.A. Wijngaards d1e3d52726 - checkconf-zone-check, unbound-checkonf only reads config, -a option to read
zone files of auth-zones and RPZ.
2026-10-19 16:19:36 +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
11 changed files with 64 additions and 19 deletions
+1 -1
View File
@@ -1077,7 +1077,7 @@ daemon_fork(struct daemon* daemon)
daemon_setup_modules(daemon);
/* read auth zonefiles */
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1,
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1, 1,
&daemon->use_rpz, daemon->env, &daemon->mods))
fatal_exit("auth_zones could not be setup");
+1 -1
View File
@@ -5980,7 +5980,7 @@ fr_construct_from_config(struct fast_reload_thread* fr,
fr_construct_clear(ct);
return 0;
}
if(!auth_zones_apply_cfg(ct->auth_zones, newcfg, 1, &ct->use_rpz,
if(!auth_zones_apply_cfg(ct->auth_zones, newcfg, 1, 1, &ct->use_rpz,
fr->worker->daemon->env, &fr->worker->daemon->mods)) {
fr_construct_clear(ct);
return 0;
+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_protect(&dtio->wakeup_timer_lock, &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;
}
@@ -315,6 +320,7 @@ void dt_io_thread_delete(struct dt_io_thread* dtio)
struct dt_io_list_item* item, *nextitem;
if(!dtio) return;
lock_basic_destroy(&dtio->wakeup_timer_lock);
lock_basic_destroy(&dtio->io_list_lock);
item=dtio->io_list;
while(item) {
nextitem = item->next;
@@ -463,9 +469,11 @@ int dt_io_thread_register_queue(struct dt_io_thread* dtio,
mq->dtio = dtio;
lock_basic_unlock(&mq->lock);
item->queue = mq;
lock_basic_lock(&dtio->io_list_lock);
item->next = dtio->io_list;
dtio->io_list = item;
dtio->io_list_iter = NULL;
lock_basic_unlock(&dtio->io_list_lock);
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;
if(!dtio) return;
lock_basic_lock(&dtio->io_list_lock);
item = dtio->io_list;
while(item) {
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);
free(item);
dtio->io_list_iter = NULL;
lock_basic_unlock(&dtio->io_list_lock);
return;
}
prev = item;
item = item->next;
}
lock_basic_unlock(&dtio->io_list_lock);
}
/** 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;
lock_basic_lock(&dtio->io_list_lock);
spot = dtio->io_list_iter;
/* use the next queue for the next message lookup,
* 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 */
item = spot;
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;
}
item = item->next;
}
/* scan starting at the start-of-list (to wrap around the end) */
item = dtio->io_list;
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;
}
item = item->next;
}
lock_basic_unlock(&dtio->io_list_lock);
return 0;
}
+2
View File
@@ -123,6 +123,8 @@ struct dt_io_thread {
int threadnum;
/** event base, for event handling */
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 */
struct dt_io_list_item* io_list;
/** 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
- Fix unit test for root_zonemd with updated root key.
+6 -1
View File
@@ -42,7 +42,7 @@ unbound-checkconf(8)
Synopsis
--------
**unbound-checkconf** [``-hf``] [``-o option``] [cfgfile]
**unbound-checkconf** [``-ahf``] [``-o option``] [cfgfile]
Description
-----------
@@ -54,6 +54,11 @@ The config file syntax is described in
The available options are:
.. option:: -a
Also read the zonefiles for auth-zones and RPZ.
It checks if the syntax is okay of the zonefiles.
.. option:: -h
Show the version and commandline option help.
+1 -1
View File
@@ -86,7 +86,7 @@ context_finalize(struct ub_ctx* ctx)
return UB_NOMEM;
if(!local_zones_apply_cfg(ctx->local_zones, cfg))
return UB_INITFAIL;
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, 1, &is_rpz,
ctx->env, &ctx->mods))
return UB_INITFAIL;
if(!(ctx->env->fwds = forwards_create()) ||
+5 -3
View File
@@ -2350,7 +2350,7 @@ az_delete_deleted_zones(struct auth_zones* az)
}
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
int setup, int* is_rpz, struct module_env* env,
int setup, int readauth, int* is_rpz, struct module_env* env,
struct module_stack* mods)
{
struct config_auth* p;
@@ -2367,8 +2367,10 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
}
}
az_delete_deleted_zones(az);
if(!auth_zones_read_zones(az, cfg, env, mods))
return 0;
if(readauth) {
if(!auth_zones_read_zones(az, cfg, env, mods))
return 0;
}
if(setup) {
if(!auth_zones_setup_zones(az))
return 0;
+3 -1
View File
@@ -514,13 +514,15 @@ struct auth_zones* auth_zones_create(void);
* @param az: auth zones structure
* @param cfg: config to apply.
* @param setup: if true, also sets up values in the auth zones structure
* @param readauth: if true, reads zone files. False to omit zone file read,
* for use by checkconf.
* @param is_rpz: set to 1 if at least one RPZ zone is configured.
* @param env: environment for offline verification.
* @param mods: modules in environment.
* @return false on failure.
*/
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
int setup, int* is_rpz, struct module_env* env,
int setup, int readauth, int* is_rpz, struct module_env* env,
struct module_stack* mods);
/** initial pick up of worker timeouts, ties events to worker event loop
+13 -6
View File
@@ -90,6 +90,7 @@ usage(void)
printf("Usage: unbound-checkconf [file]\n");
printf(" Checks unbound configuration file for errors.\n");
printf("file if omitted %s is used.\n", CONFIGFILE);
printf("-a read zone files of auth-zones and RPZ.\n");
printf("-o option print value of option to stdout.\n");
printf("-f output full pathname with chroot applied, eg. with -o pidfile.\n");
printf("-q quiet (suppress output on success).\n");
@@ -1166,11 +1167,12 @@ check_hints(struct config_file* cfg)
/** check auth zones */
static void
check_auth(struct config_file* cfg)
check_auth(struct config_file* cfg, int readauth)
{
int is_rpz = 0;
struct auth_zones* az = auth_zones_create();
if(!az || !auth_zones_apply_cfg(az, cfg, 0, &is_rpz, NULL, NULL)) {
if(!az || !auth_zones_apply_cfg(az, cfg, 0, readauth, &is_rpz, NULL,
NULL)) {
fatal_exit("Could not setup authority zones");
}
if(is_rpz && !strstr(cfg->module_conf, "respip"))
@@ -1180,7 +1182,8 @@ check_auth(struct config_file* cfg)
/** check config file */
static void
checkconf(const char* cfgfile, const char* opt, int final, int quiet)
checkconf(const char* cfgfile, const char* opt, int final, int quiet,
int readauth)
{
char oldwd[4096];
struct config_file* cfg = config_create();
@@ -1212,7 +1215,7 @@ checkconf(const char* cfgfile, const char* opt, int final, int quiet)
#endif
check_fwd(cfg);
check_hints(cfg);
check_auth(cfg);
check_auth(cfg, readauth);
if(!quiet) { printf("unbound-checkconf: no errors in %s\n", cfgfile); }
config_delete(cfg);
}
@@ -1228,6 +1231,7 @@ int main(int argc, char* argv[])
int c;
int final = 0;
int quiet = 0;
int readauth = 0;
const char* f;
const char* opt = NULL;
const char* cfgfile = CONFIGFILE;
@@ -1240,8 +1244,11 @@ int main(int argc, char* argv[])
cfgfile = CONFIGFILE;
#endif /* USE_WINSOCK */
/* parse the options */
while( (c=getopt(argc, argv, "fhqo:")) != -1) {
while( (c=getopt(argc, argv, "afhqo:")) != -1) {
switch(c) {
case 'a':
readauth = 1;
break;
case 'f':
final = 1;
break;
@@ -1264,7 +1271,7 @@ int main(int argc, char* argv[])
if(argc == 1)
f = argv[0];
else f = cfgfile;
checkconf(f, opt, final, quiet);
checkconf(f, opt, final, quiet, readauth);
checklock_stop();
return 0;
}
+5 -3
View File
@@ -134,11 +134,11 @@ nsec_at_apex(sldns_buffer* pkt)
}
/* 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 */
uint8_t win, blen, bits;
/* 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);
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);
sldns_buffer_set_position(pkt, (size_t)(here-sldns_buffer_begin(pkt)));
/* 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;
}
sldns_buffer_skip(pkt, 4); /* ttl */
if(sldns_buffer_read_u16(pkt) < 19) /* too short */ {
sldns_buffer_set_position(pkt, pos);