]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3708. [bug] Address a portentry locking issue in dispatch.c.
authorMark Andrews <marka@isc.org>
Wed, 15 Jan 2014 04:55:35 +0000 (15:55 +1100)
committerMark Andrews <marka@isc.org>
Wed, 15 Jan 2014 04:55:35 +0000 (15:55 +1100)
                        [RT #35128]

CHANGES
lib/dns/dispatch.c

diff --git a/CHANGES b/CHANGES
index d0668454396694981c4852514a4f206e77ddb4b9..5bffadd9d5f4ead4de45ca83d6a30c14a6063b72 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3708.  [bug]           Address a portentry locking issue in dispatch.c.
+                       [RT #35128]
+
 3707.  [bug]           irs_resconf_load now returns ISC_R_FILENOTFOUND
                        on a missing resolv.conf file and initializes the
                        structure as if it had been configured with:
index a370c546f87056a3abf087c0cb3d169e04e28441..38505562dc2fb3448628312677e60c79a375c9c5 100644 (file)
@@ -755,6 +755,7 @@ port_search(dns_dispatch_t *disp, in_port_t port) {
 static dispportentry_t *
 new_portentry(dns_dispatch_t *disp, in_port_t port) {
        dispportentry_t *portentry;
+       dns_qid_t *qid;
 
        REQUIRE(disp->port_table != NULL);
 
@@ -763,10 +764,13 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) {
                return (portentry);
 
        portentry->port = port;
-       portentry->refs = 0;
+       portentry->refs = 1;
        ISC_LINK_INIT(portentry, link);
+       qid = DNS_QID(disp);
+       LOCK(&qid->lock);
        ISC_LIST_APPEND(disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE],
                        portentry, link);
+       UNLOCK(&qid->lock);
 
        return (portentry);
 }
@@ -777,7 +781,6 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) {
 static void
 deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
        dispportentry_t *portentry = *portentryp;
-       isc_boolean_t unlink = ISC_FALSE;
        dns_qid_t *qid;
 
        REQUIRE(disp->port_table != NULL);
@@ -786,15 +789,14 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
        qid = DNS_QID(disp);
        LOCK(&qid->lock);
        portentry->refs--;
-       unlink = ISC_TF(portentry->refs == 0);
-       UNLOCK(&qid->lock);
 
-       if (unlink) {
+       if (portentry->refs == 0) {
                ISC_LIST_UNLINK(disp->port_table[portentry->port %
                                                 DNS_DISPATCH_PORTTABLESIZE],
                                portentry, link);
                isc_mempool_put(disp->portpool, portentry);
        }
+       UNLOCK(&qid->lock);
 
        *portentryp = NULL;
 }
@@ -916,8 +918,11 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
                                        result = ISC_R_NOMEMORY;
                                        break;
                                }
+                       } else {
+                               LOCK(&qid->lock);
+                               portentry->refs++;
+                               UNLOCK(&qid->lock);
                        }
-                       portentry->refs++;
                        break;
                } else if (result == ISC_R_NOPERM) {
                        char buf[ISC_SOCKADDR_FORMATSIZE];