]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[v9_8] dispatch.c race
authorEvan Hunt <each@isc.org>
Mon, 23 Dec 2013 17:53:08 +0000 (09:53 -0800)
committerEvan Hunt <each@isc.org>
Mon, 23 Dec 2013 17:53:08 +0000 (09:53 -0800)
3695. [bug] Address a possible race in dispatch.c. [RT #35107]

(cherry picked from commit 2b258a1f5b02488c6a36ac1b0a7535b42ea6fd34)

CHANGES
lib/dns/dispatch.c

diff --git a/CHANGES b/CHANGES
index a153df4ce3aedcab47be0ce0ccf89a2376569a28..4b18cf076186103a9afb60547f09d3919b84bb6c 100644 (file)
--- 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]
 
index 9848ac28a64a3389086b0b7367122278521d027b..ba4221a154cba1d476a0d67701cdcd4246664dec 100644 (file)
@@ -695,8 +695,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) {
@@ -813,6 +813,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]);
@@ -1046,6 +1047,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]);
@@ -2507,8 +2509,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;
@@ -3110,16 +3111,15 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
         * Try somewhat hard to find an unique ID.
         */
        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);
        }
 
        if (!ok) {
@@ -3131,9 +3131,9 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
        res = isc_mempool_get(disp->mgr->rpool);
        if (res == NULL) {
                UNLOCK(&qid->lock);
-               UNLOCK(&disp->lock);
                if (dispsocket != NULL)
                        destroy_dispsocket(disp, &dispsocket);
+               UNLOCK(&disp->lock);
                return (ISC_R_NOMEMORY);
        }