]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Do not destroy IXFR journal in xfrin_end()
authorMichał Kępień <michal@isc.org>
Wed, 20 Dec 2023 16:21:14 +0000 (17:21 +0100)
committerMichał Kępień <michal@isc.org>
Wed, 20 Dec 2023 16:21:14 +0000 (17:21 +0100)
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.

lib/dns/probes.d
lib/dns/xfrin.c

index 2d9f2c3d62a68256ae72044b5eff7682c113ead7..f5abec43ca1d135cd671d4962fba6b714295c52c 100644 (file)
@@ -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);
index 697e8507c902bb51f320cef528ae0d105b424437..9ac923f5e7035a7a03d4872b5a7ab77d5a4fc0fa 100644 (file)
@@ -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);