]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4857. [bug] Maintain attach/detach semantics for event->db,
authorMark Andrews <marka@isc.org>
Thu, 4 Jan 2018 02:07:51 +0000 (13:07 +1100)
committerMark Andrews <marka@isc.org>
Thu, 4 Jan 2018 02:07:51 +0000 (13:07 +1100)
                        event->node, event->rdataset and event->sigrdataset
                        in query.c. [RT #46891]

CHANGES
bin/named/query.c

diff --git a/CHANGES b/CHANGES
index 4c63aeda7c4c52dfe48355c966ef50f00306c436..8bfb51c0ef1e4d2db1570936d938d057923b8cbc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+4857.  [bug]           Maintain attach/detach semantics for event->db,
+                       event->node, event->rdataset and event->sigrdataset
+                       in query.c. [RT #46891]
+
 4856.  [bug]           'rndc zonestatus' reported the wrong underlying type
                        for a inline slave zone. [RT #46875]
 
index a432811fc7a173e945952b2cb8435592e6227a07..9b1edb73bd1331036c5bfa68a73d14211a272582 100644 (file)
@@ -1442,7 +1442,6 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
         * the GLUEOK flag.  Glue will be looked for later, but not
         * necessarily in the same database.
         */
-       node = NULL;
        result = dns_db_findext(db, name, version, type,
                                client->query.dboptions,
                                client->now, &node, fname, &cm, &ci,
@@ -3890,10 +3889,37 @@ query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db,
                       dbuf, DNS_SECTION_AUTHORITY);
 }
 
+static void
+free_devent(ns_client_t *client, isc_event_t **eventp,
+           dns_fetchevent_t **deventp)
+{
+       dns_fetchevent_t *devent = *deventp;
+
+       REQUIRE((void*)(*eventp) == (void *)(*deventp));
+
+       if (devent->fetch != NULL)
+               dns_resolver_destroyfetch(&devent->fetch);
+       if (devent->node != NULL)
+               dns_db_detachnode(devent->db, &devent->node);
+       if (devent->db != NULL)
+               dns_db_detach(&devent->db);
+       if (devent->rdataset != NULL)
+               query_putrdataset(client, &devent->rdataset);
+       if (devent->rdataset != NULL)
+               query_putrdataset(client, &devent->sigrdataset);
+       /*
+        * If the two pointers are the same then leave the setting of
+        * (*deventp) to NULL to isc_event_free.
+        */
+       if ((void *)eventp != (void *)deventp)
+               (*deventp) = NULL;
+       isc_event_free(eventp);
+}
+
 static void
 query_resume(isc_task_t *task, isc_event_t *event) {
        dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
-       dns_fetch_t *fetch;
+       dns_fetch_t *fetch = NULL;
        ns_client_t *client;
        isc_boolean_t fetch_canceled, client_shuttingdown;
        isc_result_t result;
@@ -3935,8 +3961,7 @@ query_resume(isc_task_t *task, isc_event_t *event) {
        INSIST(client->query.fetch == NULL);
 
        client->query.attributes &= ~NS_QUERYATTR_RECURSING;
-       fetch = devent->fetch;
-       devent->fetch = NULL;
+       SAVE(fetch, devent->fetch);
 
        /*
         * If this client is shutting down, or this transaction
@@ -3944,14 +3969,7 @@ query_resume(isc_task_t *task, isc_event_t *event) {
         */
        client_shuttingdown = ns_client_shuttingdown(client);
        if (fetch_canceled || client_shuttingdown) {
-               if (devent->node != NULL)
-                       dns_db_detachnode(devent->db, &devent->node);
-               if (devent->db != NULL)
-                       dns_db_detach(&devent->db);
-               query_putrdataset(client, &devent->rdataset);
-               if (devent->sigrdataset != NULL)
-                       query_putrdataset(client, &devent->sigrdataset);
-               isc_event_free(&event);
+               free_devent(client, &event, &devent);
                if (fetch_canceled) {
                        CTRACE(ISC_LOG_ERROR, "fetch cancelled");
                        query_error(client, DNS_R_SERVFAIL, __LINE__);
@@ -3998,14 +4016,7 @@ prefetch_done(isc_task_t *task, isc_event_t *event) {
                client->query.prefetch = NULL;
        }
        UNLOCK(&client->query.fetchlock);
-       if (devent->fetch != NULL)
-               dns_resolver_destroyfetch(&devent->fetch);
-       if (devent->node != NULL)
-               dns_db_detachnode(devent->db, &devent->node);
-       if (devent->db != NULL)
-               dns_db_detach(&devent->db);
-       query_putrdataset(client, &devent->rdataset);
-       isc_event_free(&event);
+       free_devent(client, &event, &devent);
        ns_client_detach(&client);
 }
 
@@ -4398,14 +4409,11 @@ rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
                INSIST(dns_name_equal(name, st->r_name));
                INSIST(*rdatasetp == NULL ||
                       !dns_rdataset_isassociated(*rdatasetp));
-               INSIST(*dbp == NULL);
                st->state &= ~DNS_RPZ_RECURSING;
-               *dbp = st->r.db;
-               st->r.db = NULL;
+               RESTORE(*dbp, st->r.db);
                if (*rdatasetp != NULL)
                        query_putrdataset(client, rdatasetp);
-               *rdatasetp = st->r.r_rdataset;
-               st->r.r_rdataset = NULL;
+               RESTORE(*rdatasetp, st->r.r_rdataset);
                result = st->r.r_result;
                if (result == DNS_R_DELEGATION) {
                        CTRACE(ISC_LOG_ERROR, "RPZ recursing");
@@ -6692,11 +6700,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        RESTORE(sigrdataset, rpz_st->q.sigrdataset);
                        qtype = rpz_st->q.qtype;
 
-                       rpz_st->r.db = event->db;
                        if (event->node != NULL)
                                dns_db_detachnode(event->db, &event->node);
+                       SAVE(rpz_st->r.db, event->db);
                        rpz_st->r.r_type = event->qtype;
-                       rpz_st->r.r_rdataset = event->rdataset;
+                       SAVE(rpz_st->r.r_rdataset, event->rdataset);
                        query_putrdataset(client, &event->sigrdataset);
                } else if (REDIRECT(client)) {
                        /*
@@ -6741,10 +6749,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        authoritative = ISC_FALSE;
 
                        qtype = event->qtype;
-                       db = event->db;
-                       node = event->node;
-                       rdataset = event->rdataset;
-                       sigrdataset = event->sigrdataset;
+                       SAVE(db, event->db);
+                       SAVE(node, event->node);
+                       SAVE(rdataset, event->rdataset);
+                       SAVE(sigrdataset, event->sigrdataset);
                }
                INSIST(rdataset != NULL);
 
@@ -6818,7 +6826,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                    (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
                        rpz_st->r.r_result = event->result;
                        result = rpz_st->q.result;
-                       isc_event_free(ISC_EVENT_PTR(&event));
+                       free_devent(client, ISC_EVENT_PTR(&event), &event);
                } else if (REDIRECT(client)) {
                        result = client->query.redirect.result;
                        is_zone = client->query.redirect.is_zone;
@@ -7503,6 +7511,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                         * We're authoritative for an ancestor of QNAME.
                         */
                        if (!USECACHE(client) || !RECURSIONOK(client)) {
+                               isc_boolean_t detach = ISC_FALSE;
+
                                dns_fixedname_init(&fixed);
                                dns_name_copy(fname,
                                              dns_fixedname_name(&fixed), NULL);
@@ -7522,7 +7532,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                 * We enable the retrieval of glue for this
                                 * database by setting client->query.gluedb.
                                 */
-                               client->query.gluedb = db;
+                               if (db != NULL &&
+                                   client->query.gluedb == NULL) {
+                                       dns_db_attach(db,
+                                                     &client->query.gluedb);
+                                       detach = ISC_TRUE;
+                               }
                                client->query.isreferral = ISC_TRUE;
                                /*
                                 * We must ensure NOADDITIONAL is off,
@@ -7539,7 +7554,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                query_addrrset(client, &fname,
                                               &rdataset, sigrdatasetp,
                                               dbuf, DNS_SECTION_AUTHORITY);
-                               client->query.gluedb = NULL;
+                               if (detach) {
+                                       dns_db_detach(&client->query.gluedb);
+                               }
                                if (WANTDNSSEC(client))
                                        query_addds(client, db, node, version,
                                                   dns_fixedname_name(&fixed));
@@ -7642,6 +7659,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                else
                                        RECURSE_ERROR(result);
                        } else {
+                               isc_boolean_t detach = ISC_FALSE;
+
                                dns_fixedname_init(&fixed);
                                dns_name_copy(fname,
                                              dns_fixedname_name(&fixed), NULL);
@@ -7650,8 +7669,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                 */
                                client->query.attributes |=
                                        NS_QUERYATTR_CACHEGLUEOK;
-                               client->query.gluedb = zdb;
                                client->query.isreferral = ISC_TRUE;
+
+                               if (zdb != NULL &&
+                                   client->query.gluedb == NULL) {
+                                       dns_db_attach(zdb,
+                                                     &client->query.gluedb);
+                                       detach = ISC_TRUE;
+                               }
+
                                /*
                                 * We must ensure NOADDITIONAL is off,
                                 * because the generation of
@@ -7667,9 +7693,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                query_addrrset(client, &fname,
                                               &rdataset, sigrdatasetp,
                                               dbuf, DNS_SECTION_AUTHORITY);
-                               client->query.gluedb = NULL;
                                client->query.attributes &=
                                        ~NS_QUERYATTR_CACHEGLUEOK;
+                               if (detach) {
+                                       dns_db_detach(&client->query.gluedb);
+                               }
+
                                if (WANTDNSSEC(client))
                                        query_addds(client, db, node, version,
                                                   dns_fixedname_name(&fixed));
@@ -8938,8 +8967,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                        query_releasename(client, &zfname);
                dns_db_detach(&zdb);
        }
-       if (event != NULL)
-               isc_event_free(ISC_EVENT_PTR(&event));
+       if (event != NULL) {
+               free_devent(client, ISC_EVENT_PTR(&event), &event);
+       }
 
        /*
         * AA bit.