From: Mark Andrews Date: Tue, 8 Nov 2011 21:20:57 +0000 (+0000) Subject: 3212. [bug] rbtdb.c: failed to remove a node from the deadnodes X-Git-Tag: v9.6-ESV-R6b1~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30a0de49494290cda0590f0c9857b08968c020cb;p=thirdparty%2Fbind9.git 3212. [bug] rbtdb.c: failed to remove a node from the deadnodes list prior to adding a reference to it leading a possible assertion failure. [RT #23219] --- diff --git a/CHANGES b/CHANGES index de822c47cc0..14c67d4427f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3212. [bug] rbtdb.c: failed to remove a node from the deadnodes + list prior to adding a reference to it leading a + possible assertion failure. [RT #23219] + 3208. [bug] 'dig -y' handle unknown tsig alorithm better. [RT #25522] diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 93a2a32ac7d..7a5a5841456 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.270.12.34 2011/10/13 00:37:34 marka Exp $ */ +/* $Id: rbtdb.c,v 1.270.12.35 2011/11/08 21:20:57 marka Exp $ */ /*! \file */ @@ -1549,6 +1549,7 @@ new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) { unsigned int lockrefs, noderefs; isc_refcount_t *lockref; + INSIST(!ISC_LINK_LINKED(node, deadlink)); dns_rbtnode_refincrement0(node, &noderefs); if (noderefs == 1) { /* this is the first reference to the node */ lockref = &rbtdb->node_locks[node->locknum].references; @@ -1575,8 +1576,6 @@ reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, isc_boolean_t need_relock = ISC_FALSE; NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock); - new_reference(rbtdb, node); - NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock, isc_rwlocktype_read); if (ISC_LINK_LINKED(node, deadlink)) @@ -1597,7 +1596,7 @@ reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock, isc_rwlocktype_write); } - + new_reference(rbtdb, node); NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock); } @@ -1763,6 +1762,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, ISC_LOG_INFO, "decrement_reference: failed to " "allocate pruning event"); + INSIST(node->data == NULL); INSIST(!ISC_LINK_LINKED(node, deadlink)); ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, deadlink); @@ -1801,6 +1801,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, } } } else if (dns_rbtnode_refcurrent(node) == 0) { + INSIST(node->data == NULL); INSIST(!ISC_LINK_LINKED(node, deadlink)); ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, deadlink); } else @@ -1872,11 +1873,10 @@ prune_tree(isc_task_t *task, isc_event_t *event) { * from the list beforehand as we do in * reactivate_node(). */ - new_reference(rbtdb, parent); - if (ISC_LINK_LINKED(parent, deadlink)) { + if (ISC_LINK_LINKED(parent, deadlink)) ISC_LIST_UNLINK(rbtdb->deadnodes[locknum], parent, deadlink); - } + new_reference(rbtdb, parent); } else parent = NULL; @@ -2461,20 +2461,19 @@ add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) { } static isc_result_t -findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, - dns_dbnode_t **nodep) +findnodeintree(dns_rbtdb_t *rbtdb, dns_rbt_t *tree, dns_name_t *name, + isc_boolean_t create, dns_dbnode_t **nodep) { - dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; dns_rbtnode_t *node = NULL; dns_name_t nodename; isc_result_t result; isc_rwlocktype_t locktype = isc_rwlocktype_read; - REQUIRE(VALID_RBTDB(rbtdb)); + INSIST(tree == rbtdb->tree || tree == rbtdb->nsec3); dns_name_init(&nodename, NULL); RWLOCK(&rbtdb->tree_lock, locktype); - result = dns_rbt_findnode(rbtdb->tree, name, NULL, &node, NULL, + result = dns_rbt_findnode(tree, name, NULL, &node, NULL, DNS_RBTFIND_EMPTYDATA, NULL, NULL); if (result != ISC_R_SUCCESS) { RWUNLOCK(&rbtdb->tree_lock, locktype); @@ -2490,7 +2489,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, locktype = isc_rwlocktype_write; RWLOCK(&rbtdb->tree_lock, locktype); node = NULL; - result = dns_rbt_addnode(rbtdb->tree, name, &node); + result = dns_rbt_addnode(tree, name, &node); if (result == ISC_R_SUCCESS) { dns_rbt_namefromnode(node, &nodename); #ifdef DNS_RBT_USEHASH @@ -2499,21 +2498,31 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, node->locknum = dns_name_hash(&nodename, ISC_TRUE) % rbtdb->node_lock_count; #endif - node->nsec3 = 0; - add_empty_wildcards(rbtdb, name); - - if (dns_name_iswildcard(name)) { - result = add_wildcard_magic(rbtdb, name); - if (result != ISC_R_SUCCESS) { - RWUNLOCK(&rbtdb->tree_lock, locktype); - return (result); + if (tree == rbtdb->tree) { + node->nsec3 = 0; + add_empty_wildcards(rbtdb, name); + + if (dns_name_iswildcard(name)) { + result = add_wildcard_magic(rbtdb, + name); + if (result != ISC_R_SUCCESS) { + RWUNLOCK(&rbtdb->tree_lock, + locktype); + return (result); + } } } + if (tree == rbtdb->nsec3) + node->nsec = 1; } else if (result != ISC_R_EXISTS) { RWUNLOCK(&rbtdb->tree_lock, locktype); return (result); } } + + if (tree == rbtdb->nsec3) + INSIST(node->nsec == 1); + reactivate_node(rbtdb, node, locktype); RWUNLOCK(&rbtdb->tree_lock, locktype); @@ -2523,59 +2532,25 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, } static isc_result_t -findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create, +findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, dns_dbnode_t **nodep) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - dns_rbtnode_t *node = NULL; - dns_name_t nodename; - isc_result_t result; - isc_rwlocktype_t locktype = isc_rwlocktype_read; REQUIRE(VALID_RBTDB(rbtdb)); - dns_name_init(&nodename, NULL); - RWLOCK(&rbtdb->tree_lock, locktype); - result = dns_rbt_findnode(rbtdb->nsec3, name, NULL, &node, NULL, - DNS_RBTFIND_EMPTYDATA, NULL, NULL); - if (result != ISC_R_SUCCESS) { - RWUNLOCK(&rbtdb->tree_lock, locktype); - if (!create) { - if (result == DNS_R_PARTIALMATCH) - result = ISC_R_NOTFOUND; - return (result); - } - /* - * It would be nice to try to upgrade the lock instead of - * unlocking then relocking. - */ - locktype = isc_rwlocktype_write; - RWLOCK(&rbtdb->tree_lock, locktype); - node = NULL; - result = dns_rbt_addnode(rbtdb->nsec3, name, &node); - if (result == ISC_R_SUCCESS) { - dns_rbt_namefromnode(node, &nodename); -#ifdef DNS_RBT_USEHASH - node->locknum = node->hashval % rbtdb->node_lock_count; -#else - node->locknum = dns_name_hash(&nodename, ISC_TRUE) % - rbtdb->node_lock_count; -#endif - node->nsec3 = 1U; - } else if (result != ISC_R_EXISTS) { - RWUNLOCK(&rbtdb->tree_lock, locktype); - return (result); - } - } else - INSIST(node->nsec3); - NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock); - new_reference(rbtdb, node); - NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock); - RWUNLOCK(&rbtdb->tree_lock, locktype); + return (findnodeintree(rbtdb, rbtdb->tree, name, create, nodep)); +} - *nodep = (dns_dbnode_t *)node; +static isc_result_t +findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create, + dns_dbnode_t **nodep) +{ + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - return (ISC_R_SUCCESS); + REQUIRE(VALID_RBTDB(rbtdb)); + + return (findnodeintree(rbtdb, rbtdb->nsec3, name, create, nodep)); } static isc_result_t