]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
352. [bug] Race condition in dns_client_t startup could cause
authorAndreas Gustafsson <source@isc.org>
Wed, 26 Jul 2000 17:39:12 +0000 (17:39 +0000)
committerAndreas Gustafsson <source@isc.org>
Wed, 26 Jul 2000 17:39:12 +0000 (17:39 +0000)
                        an assertion failure.

CHANGES
bin/named/client.c
bin/named/include/named/client.h
lib/dns/include/dns/events.h

diff --git a/CHANGES b/CHANGES
index c1a5363971f5224dc351b1ec3bb8f40bb67a1c64..2cf052c588047426fc1bc1afd643529734ef4a94 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,7 @@
 
+ 352.  [bug]           Race condition in dns_client_t startup could cause
+                       an assertion failure.
+
  351.  [bug]           Constructing a response with rcode SERVFAIL to a TSIG
                        signed query could crash the server.
 
index 3df33b3bec3da7962d8579cbf21c01cecfe94318..65958be8cd1476c07ba8a9ca796dc8001b348772 100644 (file)
@@ -15,7 +15,7 @@
  * SOFTWARE.
  */
 
-/* $Id: client.c,v 1.102 2000/07/17 23:19:14 gson Exp $ */
+/* $Id: client.c,v 1.103 2000/07/26 17:39:09 gson Exp $ */
 
 #include <config.h>
 
@@ -163,6 +163,8 @@ static void clientmgr_destroy(ns_clientmgr_t *manager);
 static isc_boolean_t exit_check(ns_client_t *client);
 static void ns_client_endrequest(ns_client_t *client);
 static void ns_client_checkactive(ns_client_t *client);
+static void client_start(isc_task_t *task, isc_event_t *event);
+static void client_request(isc_task_t *task, isc_event_t *event);
 
 /*
  * Enter the inactive state.
@@ -431,6 +433,45 @@ exit_check(ns_client_t *client) {
        return (ISC_TRUE);
 }
 
+/*
+ * The client's task has received the client's control event
+ * as part of the startup process.
+ */
+static void
+client_start(isc_task_t *task, isc_event_t *event) {
+       ns_client_t *client = (ns_client_t *) event->ev_arg;
+       isc_result_t result;
+
+       INSIST(task == client->task);
+       
+       UNUSED(task);
+
+       if (TCP_CLIENT(client)) {
+               client_accept(client);
+       } else {
+               result = dns_dispatch_addrequest(client->dispatch,
+                                                client->task,
+                                                client_request,
+                                                client,
+                                                &client->dispentry);
+               
+               if (result != ISC_R_SUCCESS) {
+                       ns_client_log(client,
+                                     DNS_LOGCATEGORY_SECURITY,
+                                     NS_LOGMODULE_CLIENT,
+                                     ISC_LOG_DEBUG(3),
+                                     "dns_dispatch_addrequest() "
+                                     "failed: %s",
+                                     isc_result_totext(result));
+                       /*
+                        * Not much we can do here but log the failure; 
+                        * the client will effectively go idle.
+                        */
+               }
+       }
+}
+
+
 /*
  * The client's task has received a shutdown event.
  */
@@ -565,14 +606,14 @@ client_senddone(isc_task_t *task, isc_event_t *event) {
        ns_client_t *client;
        isc_socketevent_t *sevent = (isc_socketevent_t *) event;
 
-       UNUSED(task);
-
        REQUIRE(sevent != NULL);
        REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
        client = sevent->ev_arg;
        REQUIRE(NS_CLIENT_VALID(client));
        REQUIRE(task == client->task);
 
+       UNUSED(task);
+
        CTRACE("senddone");
 
        if (sevent->result != ISC_R_SUCCESS)
@@ -1195,6 +1236,9 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp)
        client->recursionquota = NULL;
        client->interface = NULL;
        client->peeraddr_valid = ISC_FALSE;
+       ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
+                      DNS_EVENT_CLIENTCONTROL, client_start, client, client,
+                      NULL, NULL);
        ISC_LINK_INIT(client, link);
        client->list = NULL;
 
@@ -1272,7 +1316,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) {
        UNUSED(task);
 
        INSIST(client->state == NS_CLIENTSTATE_READY);
-       
+
        INSIST(client->naccepts == 1);
        client->naccepts--;
 
@@ -1529,6 +1573,7 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
        LOCK(&manager->lock);
 
        for (i = 0; i < n; i++) {
+               isc_event_t *ev;
                /*
                 * Allocate a client.  First try to get a recycled one;
                 * if that fails, make a new one.
@@ -1553,30 +1598,16 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
                        client->attributes |= NS_CLIENTATTR_TCP;
                        isc_socket_attach(ifp->tcpsocket,
                                          &client->tcplistener);
-                       client_accept(client);
                } else {
                        dns_dispatch_attach(ifp->udpdispatch,
                                            &client->dispatch);
-                       result = dns_dispatch_addrequest(client->dispatch,
-                                                        client->task,
-                                                        client_request,
-                                                        client,
-                                                        &client->dispentry);
-                       if (result != ISC_R_SUCCESS) {
-                               ns_client_log(client,
-                                             DNS_LOGCATEGORY_SECURITY,
-                                             NS_LOGMODULE_CLIENT,
-                                             ISC_LOG_DEBUG(3),
-                                             "dns_dispatch_addrequest() "
-                                             "failed: %s",
-                                             isc_result_totext(result));
-                               isc_task_shutdown(client->task);
-                               break;
-                       }
                }
                client->manager = manager;
                ISC_LIST_APPEND(manager->active, client, link);
                client->list = &manager->active;
+
+               ev = &client->ctlevent;
+               isc_task_send(client->task, &ev);
        }
        if (i != 0) {
                /*
index 922ce2ad3cbac184918e99d498ad5580e9cfe61d..d1cb7750ec451934c812b1e408975092e5f9c309 100644 (file)
@@ -15,7 +15,7 @@
  * SOFTWARE.
  */
 
-/* $Id: client.h,v 1.37 2000/06/22 21:49:38 tale Exp $ */
+/* $Id: client.h,v 1.38 2000/07/26 17:39:11 gson Exp $ */
 
 #ifndef NAMED_CLIENT_H
 #define NAMED_CLIENT_H 1
@@ -122,6 +122,7 @@ struct ns_client {
        isc_sockaddr_t          peeraddr;
        isc_boolean_t           peeraddr_valid;
        struct in6_pktinfo      pktinfo;
+       isc_event_t             ctlevent;
        ISC_LINK(ns_client_t)   link;
        /*
         * The list 'link' is part of, or NULL if not on any list.
index d49dc5cbedfbb1f70bc38f6636dba67b07c972a7..da179433f2d2b64fd09dad9cb3ed7abf054128c8 100644 (file)
@@ -15,7 +15,7 @@
  * SOFTWARE.
  */
 
-/* $Id: events.h,v 1.24 2000/06/22 21:55:38 tale Exp $ */
+/* $Id: events.h,v 1.25 2000/07/26 17:39:12 gson Exp $ */
 
 #ifndef DNS_EVENTS_H
 #define DNS_EVENTS_H 1
@@ -52,6 +52,7 @@
 #define DNS_EVENT_NOTIFYSENDTOADDR             (ISC_EVENTCLASS_DNS + 23)
 #define DNS_EVENT_ZONE                         (ISC_EVENTCLASS_DNS + 24)
 #define DNS_EVENT_ZONESTARTXFRIN               (ISC_EVENTCLASS_DNS + 25)
+#define DNS_EVENT_CLIENTCONTROL                        (ISC_EVENTCLASS_DNS + 26)
 
 #define DNS_EVENT_FIRSTEVENT                   (ISC_EVENTCLASS_DNS + 0)
 #define DNS_EVENT_LASTEVENT                    (ISC_EVENTCLASS_DNS + 65535)