diff --git a/CHANGES b/CHANGES index 46d0d6be6b..375c431f7b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3834. [bug] The re-signing heaps were not being updated soon enough + leading to multiple re-generations of the same RRSIG + when a zone transfer was in progress. [RT #35273] + 2833. [bug] Cross compiling was broken due to calling genrandom at build time. [RT #35869] diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 481c7117cd..b905bad90a 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -609,6 +609,8 @@ static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now, isc_boolean_t tree_locked); static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader); +static void resign_delete(dns_rbtdb_t *rbtdb, rbtdb_version_t *version, + rdatasetheader_t *header); static void prune_tree(isc_task_t *task, isc_event_t *event); static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); static void rdataset_expire(dns_rdataset_t *rdataset); @@ -895,7 +897,7 @@ resign_sooner(void *v1, void *v2) { rdatasetheader_t *h1 = v1; rdatasetheader_t *h2 = v2; - if (h1->resign < h2->resign) + if (isc_serial_lt(h1->resign, h2->resign)) return (ISC_TRUE); return (ISC_FALSE); } @@ -2540,8 +2542,18 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { lock = &rbtdb->node_locks[header->node->locknum].lock; NODE_LOCK(lock, isc_rwlocktype_write); - if (rollback) - resign_insert(rbtdb, header->node->locknum, header); + if (rollback && !IGNORE(header)) { + isc_result_t result; + result = resign_insert(rbtdb, header->node->locknum, + header); + if (result != ISC_R_SUCCESS) + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_ZONE, ISC_LOG_ERROR, + "Unable to reinsert header to " + "re-signing heap: %s\n", + dns_result_totext(result)); + } decrement_reference(rbtdb, header->node, least_serial, isc_rwlocktype_write, isc_rwlocktype_none, ISC_FALSE); @@ -5855,6 +5867,24 @@ resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader) { return (result); } +static void +resign_delete(dns_rbtdb_t *rbtdb, rbtdb_version_t *version, + rdatasetheader_t *header) +{ + /* + * Remove the old header from the heap + */ + if (header != NULL && header->heap_index != 0) { + isc_heap_delete(rbtdb->heaps[header->node->locknum], + header->heap_index); + header->heap_index = 0; + if (version != NULL) { + new_reference(rbtdb, header->node); + ISC_LIST_APPEND(version->resigned_list, header, link); + } + } +} + static isc_result_t add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading, @@ -6217,9 +6247,14 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, * will not leak... for long. */ INSIST(rbtdb->heaps != NULL); - isc_heap_insert(rbtdb->heaps[idx], newheader); - } else if (RESIGN(newheader)) - resign_insert(rbtdb, idx, newheader); + (void)isc_heap_insert(rbtdb->heaps[idx], + newheader); + } else if (RESIGN(newheader)) { + resign_delete(rbtdb, rbtversion, header); + result = resign_insert(rbtdb, idx, newheader); + if (result != ISC_R_SUCCESS) + return (result); + } } } else { /* @@ -6271,7 +6306,10 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, newheader, link); isc_heap_insert(rbtdb->heaps[idx], newheader); } else if (RESIGN(newheader)) { - resign_insert(rbtdb, idx, newheader); + resign_delete(rbtdb, rbtversion, header); + result = resign_insert(rbtdb, idx, newheader); + if (result != ISC_R_SUCCESS) + return (result); } } @@ -6762,6 +6800,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, topheader->next = newheader; rbtnode->dirty = 1; changed->dirty = ISC_TRUE; + resign_delete(rbtdb, rbtversion, header); } else { /* * The rdataset doesn't exist, so we don't need to do anything @@ -7777,6 +7816,9 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) INSIST(header != NULL); header--; + if (header->heap_index == 0) + return; + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); NODE_LOCK(&rbtdb->node_locks[node->locknum].lock, isc_rwlocktype_write); @@ -7784,11 +7826,7 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) * Delete from heap and save to re-signed list so that it can * be restored if we backout of this change. */ - new_reference(rbtdb, node); - isc_heap_delete(rbtdb->heaps[node->locknum], header->heap_index); - header->heap_index = 0; - ISC_LIST_APPEND(rbtversion->resigned_list, header, link); - + resign_delete(rbtdb, rbtversion, header); NODE_UNLOCK(&rbtdb->node_locks[node->locknum].lock, isc_rwlocktype_write); RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);