Do not destroy IXFR journal in xfrin_end()
The xfrin_end() function is run when a zone transfer is finished or canceled. One of the actions it takes for incremental transfers (IXFR) is calling dns_journal_destroy() on the zone journal structure that is stored in the relevant zone transfer context (xfr->ixfr.journal). That immediately invalidates that structure as it is not reference-counted. However, since the changes present in the IXFR stream are applied to the journal asynchronously (via isc_work_enqueue()), it is possible that some zone changes may still be in the process of being written to the journal by the time xfrin_end() destroys the relevant structure. Such a scenario leads to crashes. Fix by not destroying the zone journal structure until the entire zone transfer context is destroyed. xfrin_destroy() already conditionally calls dns_journal_destroy() and when the former is called, all asynchronous work for a given zone transfer process is guaranteed to be complete.
This commit is contained in:
@@ -17,8 +17,6 @@ provider libdns {
|
||||
probe xfrin_connected(void *, char *, int);
|
||||
probe xfrin_done_callback_begin(void *, char *, int);
|
||||
probe xfrin_done_callback_end(void *, char *, int);
|
||||
probe xfrin_journal_destroy_begin(void *, char *, int);
|
||||
probe xfrin_journal_destroy_end(void *, char *, int);
|
||||
probe xfrin_read(void *, char *, int);
|
||||
probe xfrin_recv_answer(void *, char *, void *);
|
||||
probe xfrin_recv_done(void *, char *, int);
|
||||
|
||||
@@ -1656,13 +1656,6 @@ get_edns_expire(dns_xfrin_t *xfr, dns_message_t *msg) {
|
||||
|
||||
static void
|
||||
xfrin_end(dns_xfrin_t *xfr, isc_result_t result) {
|
||||
/* Close the journal. */
|
||||
if (xfr->ixfr.journal != NULL) {
|
||||
LIBDNS_XFRIN_JOURNAL_DESTROY_BEGIN(xfr, xfr->info, result);
|
||||
dns_journal_destroy(&xfr->ixfr.journal);
|
||||
LIBDNS_XFRIN_JOURNAL_DESTROY_END(xfr, xfr->info, result);
|
||||
}
|
||||
|
||||
/* Inform the caller. */
|
||||
if (xfr->done != NULL) {
|
||||
LIBDNS_XFRIN_DONE_CALLBACK_BEGIN(xfr, xfr->info, result);
|
||||
|
||||
Reference in New Issue
Block a user