diff --git a/CHANGES b/CHANGES index d5996d5624..1fac7270c2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ 1928. [bug] Race in rbtdb.c:currentversion(). [RT #15517] -1927. [placeholder] rt15518 +1927. [bug] Access to soanode or nsnode in rbtdb violated the + lock order rule and could cause a dead lock. + [RT# 15518] 1926. [bug] The Windows installer did not check for empty passwords. BINDinstall was being installed in diff --git a/bin/named/query.c b/bin/named/query.c index 8cd4237e8d..6f61c9b80d 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.273 2005/09/05 00:10:52 marka Exp $ */ +/* $Id: query.c,v 1.274 2005/10/13 01:58:31 marka Exp $ */ /*! \file */ @@ -2013,7 +2013,7 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, /* * Find the SOA. */ - result = dns_db_getsoanode(db, &node); + result = dns_db_getoriginnode(db, &node); if (result == ISC_R_SUCCESS) { result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, @@ -2029,9 +2029,6 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, result = dns_db_find(db, name, version, dns_rdatatype_soa, client->query.dboptions, 0, &node, fname, rdataset, sigrdataset); - - if (result == ISC_R_SUCCESS) - (void)dns_db_setsoanode(db, node); } if (result != ISC_R_SUCCESS) { /* @@ -2135,7 +2132,7 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { /* * Find the NS rdataset. */ - result = dns_db_getnsnode(db, &node); + result = dns_db_getoriginnode(db, &node); if (result == ISC_R_SUCCESS) { result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns, @@ -2147,9 +2144,6 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { client->query.dboptions, 0, &node, fname, rdataset, sigrdataset); CTRACE("query_addns: dns_db_find complete"); - - if (result == ISC_R_SUCCESS) - (void)dns_db_setnsnode(db, node); } if (result != ISC_R_SUCCESS) { CTRACE("query_addns: " diff --git a/lib/dns/db.c b/lib/dns/db.c index 7090da4f2d..52639b2a49 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.c,v 1.79 2005/06/28 02:55:09 marka Exp $ */ +/* $Id: db.c,v 1.80 2005/10/13 01:58:31 marka Exp $ */ /*! \file */ @@ -809,49 +809,13 @@ dns_db_unregister(dns_dbimplementation_t **dbimp) { } isc_result_t -dns_db_getsoanode(dns_db_t *db, dns_dbnode_t **nodep) { +dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { REQUIRE(DNS_DB_VALID(db)); REQUIRE(dns_db_iszone(db) == ISC_TRUE); REQUIRE(nodep != NULL && *nodep == NULL); - if (db->methods->getsoanode != NULL) - return ((db->methods->getsoanode)(db, nodep)); + if (db->methods->getoriginnode != NULL) + return ((db->methods->getoriginnode)(db, nodep)); return (ISC_R_NOTFOUND); } - -isc_result_t -dns_db_setsoanode(dns_db_t *db, dns_dbnode_t *node) { - REQUIRE(DNS_DB_VALID(db)); - REQUIRE(dns_db_iszone(db) == ISC_TRUE); - REQUIRE(node != NULL); - - if (db->methods->setsoanode != NULL) - return ((db->methods->setsoanode)(db, node)); - - return (ISC_R_FAILURE); -} - -isc_result_t -dns_db_getnsnode(dns_db_t *db, dns_dbnode_t **nodep) { - REQUIRE(DNS_DB_VALID(db)); - REQUIRE(dns_db_iszone(db) == ISC_TRUE); - REQUIRE(nodep != NULL && *nodep == NULL); - - if (db->methods->getnsnode != NULL) - return ((db->methods->getnsnode)(db, nodep)); - - return (ISC_R_NOTFOUND); -} - -isc_result_t -dns_db_setnsnode(dns_db_t *db, dns_dbnode_t *node) { - REQUIRE(DNS_DB_VALID(db)); - REQUIRE(dns_db_iszone(db) == ISC_TRUE); - REQUIRE(node != NULL); - - if (db->methods->setnsnode != NULL) - return ((db->methods->setnsnode)(db, node)); - - return (ISC_R_FAILURE); -} diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index cefa8a7501..c0462d1486 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.h,v 1.83 2005/07/18 05:58:58 marka Exp $ */ +/* $Id: db.h,v 1.84 2005/10/13 01:58:32 marka Exp $ */ #ifndef DNS_DB_H #define DNS_DB_H 1 @@ -145,10 +145,7 @@ typedef struct dns_dbmethods { isc_boolean_t (*ispersistent)(dns_db_t *db); void (*overmem)(dns_db_t *db, isc_boolean_t overmem); void (*settask)(dns_db_t *db, isc_task_t *); - isc_result_t (*getsoanode)(dns_db_t *db, dns_dbnode_t **nodep); - isc_result_t (*setsoanode)(dns_db_t *db, dns_dbnode_t *nodep); - isc_result_t (*getnsnode)(dns_db_t *db, dns_dbnode_t **nodep); - isc_result_t (*setnsnode)(dns_db_t *db, dns_dbnode_t *nodep); + isc_result_t (*getoriginnode)(dns_db_t *db, dns_dbnode_t **nodep); } dns_dbmethods_t; typedef isc_result_t @@ -1278,9 +1275,11 @@ dns_db_unregister(dns_dbimplementation_t **dbimp); */ isc_result_t -dns_db_getsoanode(dns_db_t *db, dns_dbnode_t **nodep); +dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep); /*%< - * Get a cached SOA DB node corresponding to the DB's zone. + * Get the origin DB node corresponding to the DB's zone. This function + * should typically succeed unless the underlying DB implementation doesn't + * support the feature. * * Requires: * @@ -1288,71 +1287,11 @@ dns_db_getsoanode(dns_db_t *db, dns_dbnode_t **nodep); * \li 'nodep' != NULL && '*nodep' == NULL * * Ensures: - * \li On sucess, '*nodep' will point to a DB node for the SOA RR of 'db.' + * \li On success, '*nodep' will point to the DB node of the zone's origin. * * Returns: * \li #ISC_R_SUCCESS - * \li #ISC_R_NOTFOUND - an SOA RR node has not been cached in 'db' or SOA RR - * caching is not supported for 'db' - */ - -isc_result_t -dns_db_setsoanode(dns_db_t *db, dns_dbnode_t *node); -/*%< - * Set an SOA DB node as cache corresponding to the DB's zone. If there is - * already a node set in the DB, it will be detached and replaced with the - * new one. - * - * Requires: - * - * \li 'db' is a valid zone database. - * \li 'node' is a valid DB node. - * - * Ensures: - * \li On sucess, '*nodep' will point to a DB node for the SOA RR of 'db.' - * - * Returns: - * \li #ISC_R_SUCCESS - * \li #ISC_R_FAILURE - SOA RR caching is not supported for 'db' - */ - -isc_result_t -dns_db_getnsnode(dns_db_t *db, dns_dbnode_t **nodep); -/*%< - * Get a cached NS DB node corresponding to the DB's zone. - * - * Requires: - * - * \li 'db' is a valid zone database. - * \li 'nodep' != NULL && '*nodep' == NULL - * - * Ensures: - * \li On sucess, '*nodep' will point to a DB node for the NS RR of 'db.' - * - * Returns: - * \li #ISC_R_SUCCESS - * \li #ISC_R_NOTFOUND - an NS RR node has not been cached in 'db' or NS RR - * caching is not supported for 'db' - */ - -isc_result_t -dns_db_setnsnode(dns_db_t *db, dns_dbnode_t *node); -/*%< - * Set an NS DB node as cache corresponding to the DB's zone. If there is - * already a node set in the DB, it will be detached and replaced with the - * new one. - * - * Requires: - * - * \li 'db' is a valid zone database. - * \li 'node' is a valid DB node. - * - * Ensures: - * \li On sucess, '*nodep' will point to a DB node for the NS RR of 'db.' - * - * Returns: - * \li #ISC_R_SUCCESS - * \li #ISC_R_FAILURE - NS RR caching is not supported for 'db' + * \li #ISC_R_NOTFOUND - the DB implementation does not support this feature. */ ISC_LANG_ENDDECLS diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 026627cd63..1088039f97 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.221 2005/10/13 01:19:14 marka Exp $ */ +/* $Id: rbtdb.c,v 1.222 2005/10/13 01:58:31 marka Exp $ */ /*! \file */ @@ -5272,73 +5272,30 @@ ispersistent(dns_db_t *db) { } static isc_result_t -getsoanode(dns_db_t *db, dns_dbnode_t **nodep) { +getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; + dns_rbtnode_t *onode; isc_result_t result = ISC_R_SUCCESS; REQUIRE(VALID_RBTDB(rbtdb)); REQUIRE(nodep != NULL && *nodep == NULL); - RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read); - if (rbtdb->soanode != NULL) { - attachnode(db, rbtdb->soanode, nodep); - } else + /* Note that the access to origin_node doesn't require a DB lock */ + onode = (dns_rbtnode_t *)rbtdb->origin_node; + if (onode != NULL) { + NODE_STRONGLOCK(&rbtdb->node_locks[onode->locknum].lock); + new_reference(rbtdb, onode); + NODE_STRONGUNLOCK(&rbtdb->node_locks[onode->locknum].lock); + + *nodep = rbtdb->origin_node; + } else { + INSIST(!IS_CACHE(rbtdb)); result = ISC_R_NOTFOUND; - RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read); + } return (result); } -static isc_result_t -setsoanode(dns_db_t *db, dns_dbnode_t *node) { - dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - - REQUIRE(VALID_RBTDB(rbtdb)); - REQUIRE(node != NULL); - - RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write); - if (rbtdb->soanode != NULL) - detachnode(db, &rbtdb->soanode); - attachnode(db, node, &rbtdb->soanode); - RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write); - - return (ISC_R_SUCCESS); -} - -static isc_result_t -getnsnode(dns_db_t *db, dns_dbnode_t **nodep) { - dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - isc_result_t result = ISC_R_SUCCESS; - - REQUIRE(VALID_RBTDB(rbtdb)); - REQUIRE(nodep != NULL && *nodep == NULL); - - RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read); - if (rbtdb->nsnode != NULL) { - attachnode(db, rbtdb->nsnode, nodep); - } else - result = ISC_R_NOTFOUND; - RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read); - - return (result); -} - -static isc_result_t -setnsnode(dns_db_t *db, dns_dbnode_t *node) { - dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - - REQUIRE(VALID_RBTDB(rbtdb)); - REQUIRE(node != NULL); - - RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write); - if (rbtdb->nsnode != NULL) - detachnode(db, &rbtdb->nsnode); - attachnode(db, node, &rbtdb->nsnode); - RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write); - - return (ISC_R_SUCCESS); -} - static dns_dbmethods_t zone_methods = { attach, detach, @@ -5367,10 +5324,7 @@ static dns_dbmethods_t zone_methods = { ispersistent, overmem, settask, - getsoanode, - setsoanode, - getnsnode, - setnsnode + getoriginnode }; static dns_dbmethods_t cache_methods = { @@ -5401,10 +5355,7 @@ static dns_dbmethods_t cache_methods = { ispersistent, overmem, settask, - getsoanode, - setsoanode, - getnsnode, - setnsnode + getoriginnode }; isc_result_t diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index fc6b290f69..29ca214496 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdb.c,v 1.52 2005/08/18 00:57:29 marka Exp $ */ +/* $Id: sdb.c,v 1.53 2005/10/13 01:58:32 marka Exp $ */ /*! \file */ @@ -1240,9 +1240,6 @@ static dns_dbmethods_t sdb_methods = { ispersistent, overmem, settask, - NULL, - NULL, - NULL, NULL }; diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index bd6205dac4..75bb5ed070 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.c,v 1.4 2005/09/20 06:16:26 marka Exp $ */ +/* $Id: sdlz.c,v 1.5 2005/10/13 01:58:32 marka Exp $ */ /*! \file */ @@ -1043,9 +1043,6 @@ static dns_dbmethods_t sdlzdb_methods = { overmem, settask, NULL, - NULL, - NULL, - NULL }; /*