]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3688. [bug] loadnode could return a freed node on out of memory.
authorMark Andrews <marka@isc.org>
Thu, 12 Dec 2013 01:50:37 +0000 (12:50 +1100)
committerMark Andrews <marka@isc.org>
Thu, 12 Dec 2013 01:50:37 +0000 (12:50 +1100)
                        [RT #35106]

CHANGES
lib/dns/rbtdb.c

diff --git a/CHANGES b/CHANGES
index 011537dccefcd72c927b067892baf0c491b84689..a9035341a17ff442849456c661523d379fe0f25e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3688.  [bug]           loadnode could return a freed node on out of memory.
+                       [RT #35106]
+
        --- 9.8.7b1 released ---
 
 3683.  [cleanup]       Add a more detailed "not found" message to rndc
index b87625c005b905c53e9c6fc0f9b9de637b9a2cb3..ddd4ce463c030665e970e2b855dcd1af8810c7d1 100644 (file)
@@ -6867,28 +6867,21 @@ static isc_result_t
 loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep,
         isc_boolean_t hasnsec)
 {
-       isc_result_t noderesult, nsecresult;
-       dns_rbtnode_t *nsecnode;
-
-       noderesult = dns_rbt_addnode(rbtdb->tree, name, nodep);
-
-#ifdef BIND9
-       if (noderesult == ISC_R_SUCCESS && rbtdb->rpz_cidr != NULL)
-               dns_rpz_cidr_addip(rbtdb->rpz_cidr, name);
-#endif
+       isc_result_t noderesult, nsecresult, tmpresult;
+       dns_rbtnode_t *nsecnode = NULL, *node = NULL;
 
+       noderesult = dns_rbt_addnode(rbtdb->tree, name, &node);
        if (!hasnsec)
-               return (noderesult);
+               goto done;
        if (noderesult == ISC_R_EXISTS) {
                /*
                 * Add a node to the auxiliary NSEC tree for an old node
                 * just now getting an NSEC record.
                 */
-               if ((*nodep)->nsec == DNS_RBT_NSEC_HAS_NSEC)
-                       return (noderesult);
-       } else if (noderesult != ISC_R_SUCCESS) {
-               return (noderesult);
-       }
+               if (node->nsec == DNS_RBT_NSEC_HAS_NSEC)
+                       goto done;
+       } else if (noderesult != ISC_R_SUCCESS)
+               goto done;
 
        /*
         * Build the auxiliary tree for NSECs as we go.
@@ -6898,12 +6891,11 @@ loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep,
         * Add nodes to the auxiliary tree after corresponding nodes have
         * been added to the main tree.
         */
-       nsecnode = NULL;
        nsecresult = dns_rbt_addnode(rbtdb->nsec, name, &nsecnode);
        if (nsecresult == ISC_R_SUCCESS) {
                nsecnode->nsec = DNS_RBT_NSEC_NSEC;
-               (*nodep)->nsec = DNS_RBT_NSEC_HAS_NSEC;
-               return (noderesult);
+               node->nsec = DNS_RBT_NSEC_HAS_NSEC;
+               goto done;
        }
 
        if (nsecresult == ISC_R_EXISTS) {
@@ -6914,21 +6906,41 @@ loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep,
                              ISC_LOG_WARNING,
                              "addnode: NSEC node already exists");
 #endif
-               (*nodep)->nsec = DNS_RBT_NSEC_HAS_NSEC;
-               return (noderesult);
+               node->nsec = DNS_RBT_NSEC_HAS_NSEC;
+               goto done;
        }
 
-       nsecresult = dns_rbt_deletenode(rbtdb->tree, *nodep, ISC_FALSE);
-       if (nsecresult != ISC_R_SUCCESS)
-               isc_log_write(dns_lctx,
-                             DNS_LOGCATEGORY_DATABASE,
-                             DNS_LOGMODULE_CACHE,
-                             ISC_LOG_WARNING,
-                             "loading_addrdataset: "
-                             "dns_rbt_deletenode: %s after "
-                             "dns_rbt_addnode(NSEC): %s",
-                             isc_result_totext(nsecresult),
-                             isc_result_totext(noderesult));
+       if (noderesult == ISC_R_SUCCESS) {
+               /*
+                * Remove the node we just added above.
+                */
+               tmpresult = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
+               if (tmpresult != ISC_R_SUCCESS)
+                       isc_log_write(dns_lctx,
+                                     DNS_LOGCATEGORY_DATABASE,
+                                     DNS_LOGMODULE_CACHE,
+                                     ISC_LOG_WARNING,
+                                     "loading_addrdataset: "
+                                     "dns_rbt_deletenode: %s after "
+                                     "dns_rbt_addnode(NSEC): %s",
+                                     isc_result_totext(tmpresult),
+                                     isc_result_totext(noderesult));
+
+       }
+
+       /*
+        * Set the error condition to be returned.
+        */
+       noderesult = nsecresult;
+
+ done:
+#ifdef BIND9
+       if (noderesult == ISC_R_SUCCESS && rbtdb->rpz_cidr != NULL)
+               dns_rpz_cidr_addip(rbtdb->rpz_cidr, name);
+#endif
+       if (noderesult == ISC_R_SUCCESS || noderesult == ISC_R_EXISTS)
+               *nodep = node;
+
        return (noderesult);
 }