mirror of
https://github.com/isc-projects/bind9.git
synced 2026-07-11 08:35:27 -04:00
Fix memory leak bug during zone shutdown
The dns_update_signaturesinc() updates zone signatures in chunks,
keeping its current state in 'zone->rss_state'. When a zone shuts
down, the signature update process is canceled, and all the data
in the state is not freed.
Create a new dns_update_state_clear() function which can be called
from dns_zone_free() to free the memory.
(cherry picked from commit 5e12906669)
This commit is contained in:
parent
7398fa2476
commit
9adab9e577
3 changed files with 30 additions and 14 deletions
|
|
@ -67,6 +67,9 @@ isc_result_t
|
|||
dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
||||
dns_dbversion_t *oldver, dns_dbversion_t *newver,
|
||||
dns_diff_t *diff, uint32_t sigvalidityinterval,
|
||||
dns_update_state_t **state);
|
||||
dns_update_state_t **statep);
|
||||
|
||||
void
|
||||
dns_update_state_clear(dns_update_state_t **statep, bool destroy);
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -1360,6 +1360,7 @@ dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
|||
|
||||
struct dns_update_state {
|
||||
unsigned int magic;
|
||||
isc_mem_t *mctx;
|
||||
dns_diff_t diffnames;
|
||||
dns_diff_t affected;
|
||||
dns_diff_t sig_diff;
|
||||
|
|
@ -1416,11 +1417,9 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
|||
dns_diff_t *diff, uint32_t sigvalidityinterval,
|
||||
dns_update_state_t **statep) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
dns_update_state_t mystate, *state;
|
||||
|
||||
dns_update_state_t mystate = { 0 }, *state = NULL;
|
||||
dns_difftuple_t *t, *next;
|
||||
bool flag, build_nsec;
|
||||
unsigned int i;
|
||||
dns_rdata_soa_t soa;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdataset_t rdataset;
|
||||
|
|
@ -1436,7 +1435,10 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
|||
state = &mystate;
|
||||
} else {
|
||||
state = isc_mem_get(diff->mctx, sizeof(*state));
|
||||
state->mctx = NULL;
|
||||
isc_mem_attach(diff->mctx, &state->mctx);
|
||||
}
|
||||
state->magic = STATE_MAGIC;
|
||||
|
||||
dns_diff_init(diff->mctx, &state->diffnames);
|
||||
dns_diff_init(diff->mctx, &state->affected);
|
||||
|
|
@ -1495,7 +1497,6 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
|
|||
*/
|
||||
CHECK(dns_diff_sort(diff, temp_order));
|
||||
state->state = sign_updates;
|
||||
state->magic = STATE_MAGIC;
|
||||
if (statep != NULL) {
|
||||
*statep = state;
|
||||
}
|
||||
|
|
@ -2064,6 +2065,18 @@ cleanup:
|
|||
dns_db_detachnode(db, &node);
|
||||
}
|
||||
|
||||
dns_update_state_clear(&state, state != &mystate);
|
||||
SET_IF_NOT_NULL(statep, NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
dns_update_state_clear(dns_update_state_t **statep, bool destroy) {
|
||||
REQUIRE(DNS_STATE_VALID(*statep));
|
||||
|
||||
dns_update_state_t *state = *statep;
|
||||
|
||||
dns_diff_clear(&state->sig_diff);
|
||||
dns_diff_clear(&state->nsec_diff);
|
||||
dns_diff_clear(&state->nsec_mindiff);
|
||||
|
|
@ -2072,17 +2085,15 @@ cleanup:
|
|||
dns_diff_clear(&state->diffnames);
|
||||
dns_diff_clear(&state->work);
|
||||
|
||||
for (i = 0; i < state->nkeys; i++) {
|
||||
for (size_t i = 0; i < state->nkeys; i++) {
|
||||
dst_key_free(&state->zone_keys[i]);
|
||||
}
|
||||
|
||||
if (state != &mystate) {
|
||||
if (destroy) {
|
||||
*statep = NULL;
|
||||
state->magic = 0;
|
||||
isc_mem_put(diff->mctx, state, sizeof(*state));
|
||||
isc_mem_putanddetach(&state->mctx, state, sizeof(*state));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static isc_stdtime_t
|
||||
|
|
|
|||
|
|
@ -1280,6 +1280,10 @@ zone_free(dns_zone_t *zone) {
|
|||
isc_mem_free(zone->mctx, include->name);
|
||||
isc_mem_put(zone->mctx, include, sizeof *include);
|
||||
}
|
||||
|
||||
if (zone->rss_state != NULL) {
|
||||
dns_update_state_clear(&zone->rss_state, true);
|
||||
}
|
||||
if (zone->masterfile != NULL) {
|
||||
isc_mem_free(zone->mctx, zone->masterfile);
|
||||
}
|
||||
|
|
@ -17044,9 +17048,7 @@ receive_secure_serial(void *arg) {
|
|||
|
||||
LOCK_ZONE(zone);
|
||||
|
||||
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
|
||||
!dns__zone_inline_secure(zone))
|
||||
{
|
||||
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
|
||||
/*
|
||||
* If this is a callback for a new secure serial that was
|
||||
* never processed and the zone is shutting down, then just
|
||||
|
|
@ -17062,7 +17064,7 @@ receive_secure_serial(void *arg) {
|
|||
|
||||
/* Otherwise, this is an ongoing processing, do the cleanup. */
|
||||
UNLOCK_ZONE(zone);
|
||||
CLEANUP(ISC_R_SHUTTINGDOWN);
|
||||
CHECK(ISC_R_SHUTTINGDOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue