- Fix that fast_reload when a zonemd verification lookup

it in progress with subnet loaded, deregisters the
  callback. Thanks to Qifan Zhang, Palo Alto Networks,
  for the report.
This commit is contained in:
W.C.A. Wijngaards
2026-06-15 16:16:50 +02:00
parent 8f5348ab47
commit 56e60e37ae
9 changed files with 93 additions and 14 deletions
+2 -1
View File
@@ -7612,7 +7612,8 @@ auth_zone_zonemd_stop_lookup(struct auth_zone* z, struct mesh_area* mesh)
qinfo.local_alias = NULL;
mesh_remove_callback(mesh, &qinfo, qflags,
&auth_zonemd_dnskey_lookup_callback, z);
&auth_zonemd_dnskey_lookup_callback, z,
z->zonemd_callback_unique_info);
}
/** Pick up the auth zone locks. */
+4
View File
@@ -17,6 +17,10 @@
- Fix that misconfigured `iter-scrub-ns: 0` causes request
failures. Thanks to Qifan Zhang, Palo Alto Networks,
for the report.
- Fix that fast_reload when a zonemd verification lookup
it in progress with subnet loaded, deregisters the
callback. Thanks to Qifan Zhang, Palo Alto Networks,
for the report.
12 June 2026: Wouter
- Fix that for auth-zone and rpz zones the allow-notify
+2
View File
@@ -167,6 +167,8 @@ struct ctx_query {
ub_event_callback_type cb_event;
/** for async query, the callback user arg */
void* cb_arg;
/** for async query the unique info */
void* unique_info;
/** answer message, result from resolver lookup. */
uint8_t* msg;
+6 -3
View File
@@ -642,7 +642,8 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
}
/* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) {
w->back->udp_buff, qid, libworker_fg_done_cb, q, 0,
&q->unique_info)) {
free(qinfo.qname);
return UB_NOMEM;
}
@@ -723,7 +724,8 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
if(async_id)
*async_id = q->querynum;
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) {
w->back->udp_buff, qid, libworker_event_done_cb, q, 0,
&q->unique_info)) {
free(qinfo.qname);
return UB_NOMEM;
}
@@ -861,7 +863,8 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
q->w = w;
/* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) {
w->back->udp_buff, qid, libworker_bg_done_cb, q, 0,
&q->unique_info)) {
add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0);
}
free(qinfo.qname);
+6 -3
View File
@@ -5558,7 +5558,8 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
* called straight away */
lock_basic_unlock(&xfr->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
&auth_xfer_transfer_lookup_callback, xfr, 0)) {
&auth_xfer_transfer_lookup_callback, xfr, 0,
&xfr->task_transfer->lookup_unique_info)) {
lock_basic_lock(&xfr->lock);
log_err("out of memory lookup up master %s", master->host);
return 0;
@@ -6804,7 +6805,8 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
* called straight away */
lock_basic_unlock(&xfr->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
&auth_xfer_probe_lookup_callback, xfr, 0)) {
&auth_xfer_probe_lookup_callback, xfr, 0,
&xfr->task_probe->lookup_unique_info)) {
lock_basic_lock(&xfr->lock);
log_err("out of memory lookup up master %s", master->host);
return 0;
@@ -8640,7 +8642,8 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
/* the callback can be called straight away */
lock_rw_unlock(&z->lock);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
&auth_zonemd_dnskey_lookup_callback, z, 0)) {
&auth_zonemd_dnskey_lookup_callback, z, 0,
&z->zonemd_callback_unique_info)) {
lock_rw_wrlock(&z->lock);
log_err("out of memory lookup of %s for zonemd",
(fetch_ds?"DS":"DNSKEY"));
+6
View File
@@ -144,6 +144,8 @@ struct auth_zone {
struct module_env* zonemd_callback_env;
/** for the zonemd callback, the type of data looked up */
uint16_t zonemd_callback_qtype;
/** for the zonemd callback, the unique info */
void* zonemd_callback_unique_info;
/** zone has been deleted */
int zone_deleted;
/** deletelist pointer, unused normally except during delete */
@@ -344,6 +346,8 @@ struct auth_probe {
/** for the hostname lookups, which master is current */
struct auth_master* lookup_target;
/** for the lookup, the callback unique info */
void* lookup_unique_info;
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
int lookup_aaaa;
/** we only want to do lookups for making config work (for notify),
@@ -402,6 +406,8 @@ struct auth_transfer {
/** for the hostname lookups, which master is current */
struct auth_master* lookup_target;
/** for the lookup, the callback unique info */
void* lookup_unique_info;
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
int lookup_aaaa;
+43 -4
View File
@@ -662,7 +662,8 @@ servfail_mem:
int
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru)
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru,
void** unique_info)
{
struct mesh_state* s = NULL;
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
@@ -751,6 +752,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
mesh->num_reply_states ++;
}
mesh->num_reply_addrs++;
if(unique_info)
*unique_info = s->unique;
if(added)
mesh_run(mesh, s, module_event_new, NULL);
return 1;
@@ -1969,6 +1972,25 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
return result;
}
struct mesh_state* mesh_area_find_unique(struct mesh_area* mesh,
struct respip_client_info* cinfo, struct query_info* qinfo,
uint16_t qflags, int prime, int valrec, void* unique_info)
{
struct mesh_state key;
struct mesh_state* result;
key.node.key = &key;
key.s.is_priming = prime;
key.s.is_valrec = valrec;
key.s.qinfo = *qinfo;
key.s.query_flags = qflags;
key.unique = (struct mesh_state*)unique_info;
key.s.client_info = cinfo;
result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
return result;
}
/** remove mesh state callback */
int mesh_state_del_cb(struct mesh_state* s, mesh_cb_func_type cb, void* cb_arg)
{
@@ -2700,13 +2722,30 @@ int mesh_jostle_exceeded(struct mesh_area* mesh)
}
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg)
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info)
{
struct mesh_state* s = NULL;
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
if(!s) return;
if(!mesh_state_del_cb(s, cb, cb_arg)) return;
if(s && mesh_state_del_cb(s, cb, cb_arg))
goto removed;
if(unique_info) {
s = mesh_area_find_unique(mesh, NULL, qinfo,
qflags&(BIT_RD|BIT_CD), 0, 0, unique_info);
if(s && mesh_state_del_cb(s, cb, cb_arg))
goto removed;
}
/* mesh_area_find builds key.unique=NULL and cannot match a state
* created with mesh_state_make_unique (e.g. subnetcache sets
* env->unique_mesh). Fall back to a linear scan; cb+cb_arg is an
* exact key (mesh_state_del_cb compares both).
* This works for both lookups for zonemd and for hostname authzone. */
RBTREE_FOR(s, struct mesh_state*, &mesh->all) {
if(s->cb_list && mesh_state_del_cb(s, cb, cb_arg))
goto removed;
}
return;
removed:
/* It was in the list and removed. */
log_assert(mesh->num_reply_addrs > 0);
mesh->num_reply_addrs--;
+23 -2
View File
@@ -342,11 +342,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
* @param cb_arg: callback user arg.
* @param rpz_passthru: if true, the rpz passthru was previously found and
* further rpz processing is stopped.
* @param unique_info: if nonnull, unique info is passed back to be used
* for the callback remove call. It does not need to be deallocated.
* @return 0 on error.
*/
int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf,
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru);
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru,
void** unique_info);
/**
* New prefetch message. Create new query state if needed.
@@ -543,6 +546,23 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
struct respip_client_info* cinfo, struct query_info* qinfo,
uint16_t qflags, int prime, int valrec);
/**
* Find a unique mesh state in the mesh area. Pass relevant flags.
*
* @param mesh: the mesh area to look in.
* @param cinfo: if non-NULL client specific info that may affect IP-based
* actions that apply to the query result.
* @param qinfo: what query
* @param qflags: if RD / CD bit is set or not.
* @param prime: if it is a priming query.
* @param valrec: if it is a validation-recursion query.
* @param unique_info: the unique info for the state. NULL can be passed.
* @return: mesh state or NULL if not found.
*/
struct mesh_state* mesh_area_find_unique(struct mesh_area* mesh,
struct respip_client_info* cinfo, struct query_info* qinfo,
uint16_t qflags, int prime, int valrec, void* unique_info);
/**
* Setup attachment super/sub relation between super and sub mesh state.
* The relation must not be present when calling the function.
@@ -736,8 +756,9 @@ void mesh_respond_serve_expired(struct mesh_state* mstate);
* @param qflags: flags from client query.
* @param cb: callback function.
* @param cb_arg: callback user arg.
* @param unique_info: if not NULL, used to find a unique state for removal.
*/
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg);
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info);
#endif /* SERVICES_MESH_H */
+1 -1
View File
@@ -2431,7 +2431,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
qinfo.qclass);
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
&probe_answer_cb, env, 0)) {
&probe_answer_cb, env, 0, NULL)) {
log_err("out of memory making 5011 probe");
}
}