From c7e021e2e64a73f665a3a57b6eb06670d2a21603 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 12 Aug 2016 14:08:48 +1000 Subject: [PATCH] 4439. [bug] Address race conditions getting ownernames of nodes. [RT #43005] --- CHANGES | 3 +++ bin/tests/system/dyndb/driver/db.c | 3 ++- lib/dns/db.c | 11 +++++++++++ lib/dns/ecdb.c | 3 ++- lib/dns/include/dns/db.h | 12 ++++++++++++ lib/dns/rbtdb.c | 26 ++++++++++++++++++++++++-- lib/dns/sdb.c | 3 ++- lib/dns/sdlz.c | 3 ++- lib/dns/win32/libdns.def.in | 1 + lib/dns/zone.c | 5 +++-- 10 files changed, 62 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index c177a44dd5..2e557ae642 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4439. [bug] Address race conditions getting ownernames of nodes. + [RT #43005] + 4438. [func] Use LIFO rather than FIFO when processing startup notify and refresh queries. [RT #42825] diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c index deb73a06fc..ef74e66ac9 100644 --- a/bin/tests/system/dyndb/driver/db.c +++ b/bin/tests/system/dyndb/driver/db.c @@ -622,7 +622,8 @@ static dns_dbmethods_t sampledb_methods = { findnodeext, findext, setcachestats, - hashsize + hashsize, + NULL }; /* Auxiliary driver functions. */ diff --git a/lib/dns/db.c b/lib/dns/db.c index 83c8268045..49be6e22af 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -1100,3 +1100,14 @@ dns_db_updatenotify_unregister(dns_db_t *db, return (ISC_R_NOTFOUND); } + +isc_result_t +dns_db_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) { + REQUIRE(db != NULL); + REQUIRE(node != NULL); + REQUIRE(name != NULL); + + if (db->methods->nodefullname == NULL) + return (ISC_R_NOTIMPLEMENTED); + return ((db->methods->nodefullname)(db, node, name)); +} diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c index f431bb65ef..27135bfedb 100644 --- a/lib/dns/ecdb.c +++ b/lib/dns/ecdb.c @@ -581,7 +581,8 @@ static dns_dbmethods_t ecdb_methods = { NULL, /* findnodeext */ NULL, /* findext */ NULL, /* setcachestats */ - NULL /* hashsize */ + NULL, /* hashsize */ + NULL /* nodefullname */ }; static isc_result_t diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 7c7ce9598b..c2e1228e6d 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -186,6 +186,8 @@ typedef struct dns_dbmethods { dns_rdataset_t *sigrdataset); isc_result_t (*setcachestats)(dns_db_t *db, isc_stats_t *stats); size_t (*hashsize)(dns_db_t *db); + isc_result_t (*nodefullname)(dns_db_t *db, dns_dbnode_t *node, + dns_name_t *name); } dns_dbmethods_t; typedef isc_result_t @@ -1654,6 +1656,16 @@ dns_db_updatenotify_unregister(dns_db_t *db, * */ +isc_result_t +dns_db_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name); +/*%< + * Get the name associated with a database node. + * + * Requires: + * + * \li 'db' is a valid database + * \li 'node' and 'name' are not NULL + */ ISC_LANG_ENDDECLS #endif /* DNS_DB_H */ diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 7a90020260..663cf18f6a 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -218,6 +218,7 @@ typedef isc_uint64_t rbtdb_serial_t; #define new_reference new_reference64 #define newversion newversion64 #define nodecount nodecount64 +#define nodefullname nodefullname64 #define overmem overmem64 #define previous_closest_nsec previous_closest_nsec64 #define printnode printnode64 @@ -6630,7 +6631,9 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); dns_rbt_fullnamefromnode(node, name); + RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); dns_rdataset_getownercase(rdataset, name); newheader = (rdatasetheader_t *)region.base; @@ -8061,6 +8064,23 @@ getrrsetstats(dns_db_t *db) { return (rbtdb->rrsetstats); } +static isc_result_t +nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) { + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; + dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node; + isc_result_t result; + + REQUIRE(VALID_RBTDB(rbtdb)); + REQUIRE(node != NULL); + REQUIRE(name != NULL); + + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + result = dns_rbt_fullnamefromnode(rbtnode, name); + RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); + + return (result); +} + static dns_dbmethods_t zone_methods = { attach, detach, @@ -8104,7 +8124,8 @@ static dns_dbmethods_t zone_methods = { NULL, NULL, NULL, - hashsize + hashsize, + nodefullname }; static dns_dbmethods_t cache_methods = { @@ -8150,7 +8171,8 @@ static dns_dbmethods_t cache_methods = { NULL, NULL, setcachestats, - hashsize + hashsize, + nodefullname }; isc_result_t diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index 5535ab8395..c86ef96094 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -1289,7 +1289,8 @@ static dns_dbmethods_t sdb_methods = { findnodeext, findext, NULL, /* setcachestats */ - NULL /* hashsize */ + NULL, /* hashsize */ + NULL /* nodefullname */ }; static isc_result_t diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 301cfbadf2..fb77f9b9d1 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -1323,7 +1323,8 @@ static dns_dbmethods_t sdlzdb_methods = { findnodeext, findext, NULL, /* setcachestats */ - NULL /* hashsize */ + NULL, /* hashsize */ + NULL /* nodefullname */ }; /* diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index 2c5f8f4928..ff860fa21e 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -227,6 +227,7 @@ dns_db_load2 dns_db_load3 dns_db_newversion dns_db_nodecount +dns_db_nodefullname dns_db_ondestroy dns_db_origin dns_db_overmem diff --git a/lib/dns/zone.c b/lib/dns/zone.c index d59e719eef..e3c884f5bd 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include @@ -13980,9 +13979,11 @@ checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdataset_init(&temprdataset); result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset); RUNTIME_CHECK(result == ISC_R_SUCCESS); + dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); - dns_rbtnode_nodename(node, name); + result = dns_db_nodefullname(db, node, name); + RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_rdataset_getownercase(rdataset, name); dns_rdataset_setownercase(&temprdataset, name); return (dns_db_addrdataset(db, node, version, 0, &temprdataset, -- GitLab