summaryrefslogtreecommitdiff
path: root/daemon/worker.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/worker.c')
-rw-r--r--daemon/worker.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/daemon/worker.c b/daemon/worker.c
index 2c4cf5ba6c0a..683f93169117 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -1009,6 +1009,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct query_info* lookup_qinfo = &qinfo;
struct query_info qinfo_tmp; /* placeholdoer for lookup_qinfo */
struct respip_client_info* cinfo = NULL, cinfo_tmp;
+ memset(&qinfo, 0, sizeof(qinfo));
if(error != NETEVENT_NOERROR) {
/* some bad tcp query DNS formats give these error calls */
@@ -1111,6 +1112,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(!query_info_parse(&qinfo, c->buffer)) {
verbose(VERB_ALGO, "worker parse request: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
+ memset(&qinfo, 0, sizeof(qinfo)); /* zero qinfo.qname */
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
comm_point_drop_reply(repinfo);
return 0;
@@ -1355,6 +1357,10 @@ lookup_cache:
lock_rw_unlock(&e->lock);
regional_free_all(worker->scratchpad);
goto send_reply;
+ } else {
+ /* Note that we've already released the
+ * lock if we're here after prefetch. */
+ lock_rw_unlock(&e->lock);
}
/* We've found a partial reply ending with an
* alias. Replace the lookup qinfo for the
@@ -1362,7 +1368,6 @@ lookup_cache:
* (possibly) complete the reply. As we're
* passing the "base" reply, there will be no
* more alias chasing. */
- lock_rw_unlock(&e->lock);
memset(&qinfo_tmp, 0, sizeof(qinfo_tmp));
get_cname_target(alias_rrset, &qinfo_tmp.qname,
&qinfo_tmp.qname_len);
@@ -1669,7 +1674,17 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker->env.send_query = &worker_send_query;
worker->env.alloc = &worker->alloc;
worker->env.rnd = worker->rndstate;
- worker->env.scratch = worker->scratchpad;
+ /* If case prefetch is triggered, the corresponding mesh will clear
+ * the scratchpad for the module env in the middle of request handling.
+ * It would be prone to a use-after-free kind of bug, so we avoid
+ * sharing it with worker's own scratchpad at the cost of having
+ * one more pad per worker. */
+ worker->env.scratch = regional_create_custom(cfg->msg_buffer_size);
+ if(!worker->env.scratch) {
+ log_err("malloc failure");
+ worker_delete(worker);
+ return 0;
+ }
worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
worker->env.detach_subs = &mesh_detach_subs;
worker->env.attach_sub = &mesh_attach_sub;
@@ -1758,6 +1773,7 @@ worker_delete(struct worker* worker)
comm_base_delete(worker->base);
ub_randfree(worker->rndstate);
alloc_clear(&worker->alloc);
+ regional_destroy(worker->env.scratch);
regional_destroy(worker->scratchpad);
free(worker);
}