From e029803704e21db5ad49aea8ff7de55c618b7955 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 27 Jan 2023 16:52:59 +1100 Subject: [PATCH] Handle fatal and FIPS provider interactions When fatal is called we may be holding memory allocated by OpenSSL. This may result in the reference count for the FIPS provider not going to zero and the shared library not being unloaded during OPENSSL_cleanup. When the shared library is ultimately unloaded, when all remaining dynamically loaded libraries are freed, we have already destroyed the memory context we where using to track memory leaks / late frees resulting in INSIST being called. Disable triggering the INSIST when fatal has being called. --- bin/confgen/util.c | 3 +++ bin/delv/delv.c | 1 + bin/dig/dighost.c | 1 + bin/dnssec/dnssectool.c | 2 ++ bin/named/server.c | 1 + bin/nsupdate/nsupdate.c | 1 + bin/rndc/util.c | 3 +++ bin/tools/mdig.c | 1 + bin/tools/nsec3hash.c | 2 ++ lib/isc/include/isc/tls.h | 3 +++ lib/isc/tls.c | 15 +++++++++++++-- 11 files changed, 31 insertions(+), 2 deletions(-) diff --git a/bin/confgen/util.c b/bin/confgen/util.c index 2b0a8759b5..23b7f3fd57 100644 --- a/bin/confgen/util.c +++ b/bin/confgen/util.c @@ -19,6 +19,8 @@ #include #include +#include + extern bool verbose; extern const char *progname; @@ -43,5 +45,6 @@ fatal(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + isc__tls_setfatalmode(); exit(1); } diff --git a/bin/delv/delv.c b/bin/delv/delv.c index 110d4210d7..a354a60e65 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -263,6 +263,7 @@ fatal(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + isc__tls_setfatalmode(); exit(1); } diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index cb846d32a9..55168fa699 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -411,6 +411,7 @@ fatal(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + isc__tls_setfatalmode(); digexit(); } diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c index 502548444c..62c7476559 100644 --- a/bin/dnssec/dnssectool.c +++ b/bin/dnssec/dnssectool.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -82,6 +83,7 @@ fatal(const char *format, ...) { if (fatalcallback != NULL) { (*fatalcallback)(); } + isc__tls_setfatalmode(); exit(1); } diff --git a/bin/named/server.c b/bin/named/server.c index 4534cbf994..47174867a7 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -10301,6 +10301,7 @@ fatal(const char *msg, isc_result_t result) { NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "exiting (due to fatal error)"); named_os_shutdown(); + isc__tls_setfatalmode(); exit(1); } diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 9c38a6ed68..a52dfe76e8 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -278,6 +278,7 @@ fatal(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + isc__tls_setfatalmode(); exit(1); } diff --git a/bin/rndc/util.c b/bin/rndc/util.c index 2b0a8759b5..23b7f3fd57 100644 --- a/bin/rndc/util.c +++ b/bin/rndc/util.c @@ -19,6 +19,8 @@ #include #include +#include + extern bool verbose; extern const char *progname; @@ -43,5 +45,6 @@ fatal(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + isc__tls_setfatalmode(); exit(1); } diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index 6107173129..98e72ffb2e 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -889,6 +889,7 @@ fatal(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + isc__tls_setfatalmode(); exit(-2); } diff --git a/bin/tools/nsec3hash.c b/bin/tools/nsec3hash.c index d18756dabb..aaa52d0bb0 100644 --- a/bin/tools/nsec3hash.c +++ b/bin/tools/nsec3hash.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,7 @@ fatal(const char *format, ...) { vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); + isc__tls_setfatalmode(); exit(1); } diff --git a/lib/isc/include/isc/tls.h b/lib/isc/include/isc/tls.h index 6da0361a1f..634ba65c4e 100644 --- a/lib/isc/include/isc/tls.h +++ b/lib/isc/include/isc/tls.h @@ -594,3 +594,6 @@ isc__tls_shutdown(void); void isc__tls_setdestroycheck(bool check); + +void +isc__tls_setfatalmode(void); diff --git a/lib/isc/tls.c b/lib/isc/tls.c index 569a041a8d..0e53775490 100644 --- a/lib/isc/tls.c +++ b/lib/isc/tls.c @@ -77,6 +77,8 @@ isc__tls_set_thread_id(CRYPTO_THREADID *id) { } #endif +static atomic_bool handle_fatal = false; + #if !defined(LIBRESSL_VERSION_NUMBER) /* * This was crippled with LibreSSL, so just skip it: @@ -109,7 +111,9 @@ isc__tls_free_ex(void *ptr, const char *file, int line) { if (ptr == NULL) { return; } - isc__mem_free(isc__tls_mctx, ptr, 0, file, (unsigned int)line); + if (!atomic_load(&handle_fatal) || isc__tls_mctx != NULL) { + isc__mem_free(isc__tls_mctx, ptr, 0, file, (unsigned int)line); + } } #else /* ISC_MEM_TRACKLINES */ @@ -135,7 +139,9 @@ isc__tls_free_ex(void *ptr, const char *file, int line) { if (ptr == NULL) { return; } - isc__mem_free(isc__tls_mctx, ptr, 0); + if (!atomic_load(&handle_fatal) || isc__tls_mctx != NULL) { + isc__mem_free(isc__tls_mctx, ptr, 0); + } } #endif /* ISC_MEM_TRACKLINES */ @@ -1744,3 +1750,8 @@ isc_tlsctx_set_random_session_id_context(isc_tlsctx_t *ctx) { RUNTIME_CHECK( SSL_CTX_set_session_id_context(ctx, session_id_ctx, len) == 1); } + +void +isc__tls_setfatalmode(void) { + atomic_store(&handle_fatal, true); +}