From: Marek Vavrusa Date: Sun, 22 May 2016 03:58:11 +0000 (-0700) Subject: worker: fixed corruption when follower timeouts, early free X-Git-Tag: v1.0.0~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22965f08521083b601ad9b42c779dfae9316cb63;p=thirdparty%2Fknot-resolver.git worker: fixed corruption when follower timeouts, early free * when enqueued task terminated earlier than leader task because of timeout, it wasn't dequeued from the waitlist immediately, but it didn't have any outstanding outbound queries. when leader task terminated, it removed this task and updated its outbound query, which didn't exist. this triggered a 16B write in undefined location * fixed timeout timer being scheduled for closing without holding reference to parent task --- diff --git a/daemon/worker.c b/daemon/worker.c index 1af988fe5..f7143971f 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -517,12 +517,11 @@ static void on_timeout(uv_timer_t *req) } /* Release timer handle */ task->timeout = NULL; - req_release(worker, (struct req *)req); + uv_close((uv_handle_t *)req, on_timer_close); /* Return borrowed task here */ /* Interrupt current pending request. */ task->timeouts += 1; worker->stats.timeout += 1; qr_task_step(task, NULL, NULL); - qr_task_unref(task); /* Return borrowed task */ } static bool retransmit(struct qr_task *task) @@ -544,6 +543,10 @@ static void on_retransmit(uv_timer_t *req) { uv_timer_stop(req); struct qr_task *task = req->data; + assert(task->finished == false); + assert(task->timeout != NULL); + + uv_timer_stop(req); if (!retransmit(req->data)) { /* Not possible to spawn request, start timeout timer with remaining deadline. */ uint64_t timeout = KR_CONN_RTT_MAX - task->pending_count * KR_CONN_RETRY; @@ -598,9 +601,9 @@ static void subreq_finalize(struct qr_task *task, const struct sockaddr *packet_ struct kr_query *leader_qry = array_tail(task->req.rplan.pending); for (size_t i = task->waiting.len; i --> 0;) { struct qr_task *follower = task->waiting.at[i]; - struct kr_query *qry = array_tail(follower->req.rplan.pending); /* Reuse MSGID and 0x20 secret */ - if (qry) { + if (follower->req.rplan.pending.len > 0) { + struct kr_query *qry = array_tail(follower->req.rplan.pending); qry->id = leader_qry->id; qry->secret = leader_qry->secret; leader_qry->secret = 0; /* Next will be already decoded */