From 2b258a1f5b02488c6a36ac1b0a7535b42ea6fd34 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Mon, 23 Dec 2013 09:50:18 -0800 Subject: [PATCH] [master] dispatch.c race 3695. [bug] Address a possible race in dispatch.c. [RT #35107] --- CHANGES | 2 ++ lib/dns/dispatch.c | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 8a6dd914a9..29cceb65bc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +3695. [bug] Address a possible race in dispatch.c. [RT #35107] + 3694. [bug] Warn when a key-directory is configured for a zone, but does not exist or is not a directory. [RT #35108] diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index c2e04ef42d..bac8b850dc 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -683,8 +683,8 @@ destroy_disp_ok(dns_dispatch_t *disp) /* * Called when refcount reaches 0 (and safe to destroy). * - * The dispatcher must not be locked. - * The manager must be locked. + * The dispatcher must be locked. + * The manager must not be locked. */ static void destroy_disp(isc_task_t *task, isc_event_t *event) { @@ -809,6 +809,7 @@ socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port, { dispsocket_t *dispsock; + REQUIRE(VALID_QID(qid)); REQUIRE(bucket < qid->qid_nbuckets); dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]); @@ -1045,6 +1046,7 @@ entry_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id, { dns_dispentry_t *res; + REQUIRE(VALID_QID(qid)); REQUIRE(bucket < qid->qid_nbuckets); res = ISC_LIST_HEAD(qid->qid_table[bucket]); @@ -2607,8 +2609,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, * MUST be unlocked, and not used by anything. */ static void -dispatch_free(dns_dispatch_t **dispp) -{ +dispatch_free(dns_dispatch_t **dispp) { dns_dispatch_t *disp; dns_dispatchmgr_t *mgr; int i; @@ -3271,16 +3272,15 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, */ LOCK(&qid->lock); id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp)); - bucket = dns_hash(qid, dest, id, localport); ok = ISC_FALSE; for (i = 0; i < 64; i++) { + bucket = dns_hash(qid, dest, id, localport); if (entry_search(qid, dest, id, localport, bucket) == NULL) { ok = ISC_TRUE; break; } id += qid->qid_increment; id &= 0x0000ffff; - bucket = dns_hash(qid, dest, id, localport); } UNLOCK(&qid->lock); @@ -3291,9 +3291,9 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, res = isc_mempool_get(disp->mgr->rpool); if (res == NULL) { - UNLOCK(&disp->lock); if (dispsocket != NULL) destroy_dispsocket(disp, &dispsocket); + UNLOCK(&disp->lock); return (ISC_R_NOMEMORY); }