]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[v9_8] address two more possible acache asserts
authorEvan Hunt <each@isc.org>
Fri, 26 Apr 2013 01:03:57 +0000 (18:03 -0700)
committerEvan Hunt <each@isc.org>
Fri, 26 Apr 2013 01:03:57 +0000 (18:03 -0700)
3555. [bug] Address theoretical race conditions in acache.c
(change #3553 was incomplete). [RT #33252]
(cherry picked from commit ff5ac6d4213e3e2f3f6a93db8c5e65cc170a7e2b)
(cherry picked from commit 62ebf6bbef84f9a240cfb7f528ece3b8727cfe09)

CHANGES
lib/dns/acache.c
lib/dns/include/dns/acache.h
lib/dns/rbtdb.c

diff --git a/CHANGES b/CHANGES
index ff667d75d32373a4c800310c38b290e38b12087e..5f288d857fc11ac200330907513addf10cc81519 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3555.  [bug]           Address theoretical race conditions in acache.c
+                       (change #3553 was incomplete). [RT #33252]
+
 3553.  [bug]           Address suspected double free in acache. [RT #33252]
 
 3552.  [bug]           Wrong getopt option string for 'nsupdate -r'.
index c9ca78d45e4657e2d4c80bf0b1cdd90418f00fb9..863df35535ffe9a6a5be7efe118d366d53a180a3 100644 (file)
@@ -868,7 +868,11 @@ acache_incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
                                if (entry != NULL) {
                                        /*
                                         * If we are still in the overmem
-                                        * state, keep cleaning.
+                                        * state, keep cleaning.  In case we
+                                        * exit from the loop immediately after
+                                        * this, reset next to the head entry
+                                        * as we'll expect it will be never
+                                        * NULL.
                                         */
                                        isc_log_write(dns_lctx,
                                                      DNS_LOGCATEGORY_DATABASE,
@@ -877,6 +881,7 @@ acache_incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
                                                      "acache cleaner: "
                                                      "still overmem, "
                                                      "reset and try again");
+                                       next = entry;
                                        continue;
                                }
                        }
@@ -895,7 +900,7 @@ acache_incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
         * be the starting point in the next clean-up, and reschedule another
         * batch.  If it fails, just try to continue anyway.
         */
-       INSIST(next != NULL && next != cleaner->current_entry);
+       INSIST(next != NULL);
        dns_acache_detachentry(&cleaner->current_entry);
        dns_acache_attachentry(next, &cleaner->current_entry);
 
@@ -1656,12 +1661,17 @@ dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,
        return (result);
 }
 
-void
+isc_boolean_t
 dns_acache_cancelentry(dns_acacheentry_t *entry) {
-       dns_acache_t *acache = entry->acache;
+       dns_acache_t *acache;
+       isc_boolean_t callback_active;
 
        REQUIRE(DNS_ACACHEENTRY_VALID(entry));
-       INSIST(DNS_ACACHE_VALID(acache));
+
+       acache = entry->acache;
+       callback_active = ISC_TF(entry->cbarg != NULL);
+
+       INSIST(DNS_ACACHE_VALID(entry->acache));
 
        LOCK(&acache->lock);
        ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);
@@ -1681,6 +1691,8 @@ dns_acache_cancelentry(dns_acacheentry_t *entry) {
        ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
                      isc_rwlocktype_write);
        UNLOCK(&acache->lock);
+
+       return (callback_active);
 }
 
 void
index 28990c2aab0c249d3c48154441e012d19d7a5240..d97dd64669bd046b0a7b8be9e5fb00f7defbd1b4 100644 (file)
@@ -387,7 +387,7 @@ dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,
  *     ISC_R_NOTFOUND
  */
 
-void
+isc_boolean_t
 dns_acache_cancelentry(dns_acacheentry_t *entry);
 /*
  * Cancel the use of the cache entry 'entry'.  This function is supposed to
@@ -398,6 +398,9 @@ dns_acache_cancelentry(dns_acacheentry_t *entry);
  *
  * Requires:
  *     'entry' is a valid additional cache entry.
+ *
+ * Returns:
+ *     ISC_TRUE if the entry was active when canceled
  */
 
 void
index accfa861d5324e33458989191b2c0de507539310..f6f96ab9315a02c0259cc83abc3b1ed2aa9d7243 100644 (file)
@@ -8953,9 +8953,10 @@ acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry,
 
        cbarg = *cbargp;
 
-       dns_acache_cancelentry(entry);
-       dns_db_detachnode(cbarg->db, &cbarg->node);
-       dns_db_detach(&cbarg->db);
+       if (dns_acache_cancelentry(entry)) {
+               dns_db_detachnode(cbarg->db, &cbarg->node);
+               dns_db_detach(&cbarg->db);
+       }
 
        isc_mem_put(mctx, cbarg, sizeof(acache_cbarg_t));