]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
rbtversion->glue_table_size must be read when holding a lock
authorMark Andrews <marka@isc.org>
Wed, 19 Aug 2020 04:59:02 +0000 (14:59 +1000)
committerMark Andrews <marka@isc.org>
Wed, 26 Aug 2020 11:16:04 +0000 (21:16 +1000)
lib/dns/rbtdb.c

index 9ca6de2ae08bfe4665bf8cf1e164190fa36869ca..ab7dabc2af36e9586129fdf5e1129777ececa3c9 100644 (file)
@@ -10048,7 +10048,10 @@ free_gluetable(rbtdb_version_t *version) {
        RWUNLOCK(&version->glue_rwlock, isc_rwlocktype_write);
 }
 
-static bool
+/*%
+ * Write lock (version->glue_rwlock) must be held.
+ */
+static void
 rehash_gluetable(rbtdb_version_t *version) {
        size_t oldsize, i;
        rbtdb_glue_table_node_t **oldtable;
@@ -10058,7 +10061,7 @@ rehash_gluetable(rbtdb_version_t *version) {
 
        if (ISC_LIKELY(version->glue_table_nodecount <
                       (version->glue_table_size * 3U))) {
-               return (false);
+               return;
        }
 
        oldsize = version->glue_table_size;
@@ -10076,7 +10079,7 @@ rehash_gluetable(rbtdb_version_t *version) {
        if (ISC_UNLIKELY(version->glue_table == NULL)) {
                version->glue_table = oldtable;
                version->glue_table_size = oldsize;
-               return (false);
+               return;
        }
 
        for (i = 0; i < version->glue_table_size; i++) {
@@ -10104,8 +10107,6 @@ rehash_gluetable(rbtdb_version_t *version) {
                      "resized glue table from %" PRIu64 " to "
                      "%" PRIu64,
                      (uint64_t)oldsize, (uint64_t)version->glue_table_size);
-
-       return (true);
 }
 
 static isc_result_t
@@ -10232,6 +10233,7 @@ rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version,
        rbtdb_glue_t *ge;
        rbtdb_glue_additionaldata_ctx_t ctx;
        isc_result_t result;
+       uint64_t hash;
 
        REQUIRE(rdataset->type == dns_rdatatype_ns);
        REQUIRE(rbtdb == rbtversion->rbtdb);
@@ -10249,8 +10251,7 @@ rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version,
         * the node pointer is a fixed value that won't change for a DB
         * version and can be compared directly.
         */
-       idx = isc_hash_function(&node, sizeof(node), true) %
-             rbtversion->glue_table_size;
+       hash = isc_hash_function(&node, sizeof(node), true);
 
 restart:
        /*
@@ -10259,6 +10260,8 @@ restart:
         */
        RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_read);
 
+       idx = hash % rbtversion->glue_table_size;
+
        for (cur = rbtversion->glue_table[idx]; cur != NULL; cur = cur->next) {
                if (cur->node == node) {
                        break;
@@ -10422,10 +10425,8 @@ no_glue:
 
        RWLOCK(&rbtversion->glue_rwlock, isc_rwlocktype_write);
 
-       if (ISC_UNLIKELY(rehash_gluetable(rbtversion))) {
-               idx = isc_hash_function(&node, sizeof(node), true) %
-                     rbtversion->glue_table_size;
-       }
+       rehash_gluetable(rbtversion);
+       idx = hash % rbtversion->glue_table_size;
 
        (void)dns_rdataset_additionaldata(rdataset, glue_nsdname_cb, &ctx);