diff options
Diffstat (limited to 'daemon/worker.c')
-rw-r--r-- | daemon/worker.c | 20 |
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); } |