From: Evan Hunt Date: Tue, 15 Nov 2011 21:44:53 +0000 (+0000) Subject: 3216. [bug] resolver.c:validated() was not thread-safe. [RT #26478] X-Git-Tag: v9.9.0b2~15 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=3ab9d6435a7b40812e9d8d9d1ecf537e28082e3a;p=thirdparty%2Fbind9.git 3216. [bug] resolver.c:validated() was not thread-safe. [RT #26478] --- diff --git a/CHANGES b/CHANGES index 833447c320d..7cfd2d4762e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +3216. [bug] resolver.c:validated() was not thread-safe. [RT #26478] + 3215. [bug] 'rndc recursing' could cause a core dump. [RT #26495] 3214. [func] Add 'named -U' option to set the number of UDP diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 8b3ca362912..266ea01a95e 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.440 2011/11/04 23:46:15 tbox Exp $ */ +/* $Id: resolver.c,v 1.441 2011/11/15 21:44:53 each Exp $ */ /*! \file */ @@ -453,7 +453,7 @@ static isc_result_t ncache_adderesult(dns_message_t *message, dns_rdataset_t *ardataset, isc_result_t *eresultp); static void validated(isc_task_t *task, isc_event_t *event); -static void maybe_destroy(fetchctx_t *fctx); +static void maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked); static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason, badnstype_t badtype); @@ -747,7 +747,7 @@ resquery_destroy(resquery_t **queryp) { query->fctx->nqueries--; if (SHUTTINGDOWN(query->fctx)) - maybe_destroy(query->fctx); /* Locks bucket. */ + maybe_destroy(query->fctx, ISC_FALSE); /* Locks bucket. */ query->magic = 0; isc_mem_put(query->mctx, query, sizeof(*query)); *queryp = NULL; @@ -3918,7 +3918,7 @@ clone_results(fetchctx_t *fctx) { * '*fctx' is shutting down. */ static void -maybe_destroy(fetchctx_t *fctx) { +maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) { unsigned int bucketnum; isc_boolean_t bucket_empty = ISC_FALSE; dns_resolver_t *res = fctx->res; @@ -3936,10 +3936,12 @@ maybe_destroy(fetchctx_t *fctx) { } bucketnum = fctx->bucketnum; - LOCK(&res->buckets[bucketnum].lock); + if (!locked) + LOCK(&res->buckets[bucketnum].lock); if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators)) bucket_empty = fctx_destroy(fctx); - UNLOCK(&res->buckets[bucketnum].lock); + if (!locked) + UNLOCK(&res->buckets[bucketnum].lock); if (bucket_empty) empty_bucket(res); @@ -3984,6 +3986,8 @@ validated(isc_task_t *task, isc_event_t *event) { FCTXTRACE("received validation completion event"); + LOCK(&fctx->res->buckets[fctx->bucketnum].lock); + ISC_LIST_UNLINK(fctx->validators, vevent->validator, link); fctx->validator = NULL; @@ -4005,12 +4009,11 @@ validated(isc_task_t *task, isc_event_t *event) { * so, destroy the fctx. */ if (SHUTTINGDOWN(fctx) && !sentresponse) { - maybe_destroy(fctx); /* Locks bucket. */ + maybe_destroy(fctx, ISC_TRUE); + UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); goto cleanup_event; } - LOCK(&fctx->res->buckets[fctx->bucketnum].lock); - isc_stdtime_get(&now); /* @@ -4223,7 +4226,7 @@ validated(isc_task_t *task, isc_event_t *event) { dns_db_detachnode(fctx->cache, &node); UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); if (SHUTTINGDOWN(fctx)) - maybe_destroy(fctx); /* Locks bucket. */ + maybe_destroy(fctx, ISC_FALSE); /* Locks bucket. */ goto cleanup_event; } @@ -4314,7 +4317,6 @@ validated(isc_task_t *task, isc_event_t *event) { dns_db_detachnode(fctx->cache, &node); UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); - fctx_done(fctx, result, __LINE__); /* Locks bucket. */ cleanup_event: