summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/initthread.c22
-rw-r--r--include/crypto/context.h1
-rw-r--r--providers/fips/fipsprov.c9
3 files changed, 30 insertions, 2 deletions
diff --git a/crypto/initthread.c b/crypto/initthread.c
index 54a33c3286..23ad0a0739 100644
--- a/crypto/initthread.c
+++ b/crypto/initthread.c
@@ -249,6 +249,15 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
#else
+static void ossl_arg_thread_stop(void *arg);
+
+/* Register the current thread so that we are informed if it gets stopped */
+int ossl_thread_register_fips(OSSL_LIB_CTX *libctx)
+{
+ return c_thread_start(FIPS_get_core_handle(libctx), ossl_arg_thread_stop,
+ libctx);
+}
+
void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx)
{
THREAD_EVENT_HANDLER **hands = NULL;
@@ -268,6 +277,16 @@ void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx)
if (!CRYPTO_THREAD_set_local(tlocal, hands))
goto err;
+ /*
+ * We should ideally call ossl_thread_register_fips() here. This function
+ * is called during the startup of the FIPS provider and we need to ensure
+ * that the main thread is registered to receive thread callbacks in order
+ * to free |hands| that we allocated above. However we are too early in
+ * the FIPS provider initialisation that FIPS_get_core_handle() doesn't work
+ * yet. So we defer this to the main provider OSSL_provider_init_int()
+ * function.
+ */
+
return tlocal;
err:
OPENSSL_free(hands);
@@ -379,8 +398,7 @@ int ossl_init_thread_start(const void *index, void *arg,
* libcrypto to tell us about later thread stop events. c_thread_start
* is a callback to libcrypto defined in fipsprov.c
*/
- if (!c_thread_start(FIPS_get_core_handle(ctx), ossl_arg_thread_stop,
- ctx))
+ if (!ossl_thread_register_fips(ctx))
return 0;
}
#endif
diff --git a/include/crypto/context.h b/include/crypto/context.h
index 56c68f4ec1..af81e15e1d 100644
--- a/include/crypto/context.h
+++ b/include/crypto/context.h
@@ -21,6 +21,7 @@ void *ossl_child_prov_ctx_new(OSSL_LIB_CTX *);
void *ossl_prov_drbg_nonce_ctx_new(OSSL_LIB_CTX *);
void *ossl_self_test_set_callback_new(OSSL_LIB_CTX *);
void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *);
+int ossl_thread_register_fips(OSSL_LIB_CTX *);
void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *);
void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *);
#if defined(OPENSSL_THREADS)
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index 607ee11763..7ec409710b 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -706,6 +706,15 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
fgbl->handle = handle;
/*
+ * We need to register this thread to receive thread lifecycle callbacks.
+ * This wouldn't matter if the current thread is also the same thread that
+ * closes the FIPS provider down. But if that happens on a different thread
+ * then memory leaks could otherwise occur.
+ */
+ if (!ossl_thread_register_fips(libctx))
+ goto err;
+
+ /*
* We did initial set up of selftest_params in a local copy, because we
* could not create fgbl until c_CRYPTO_zalloc was defined in the loop
* above.