Browse Source

Fix a memleak in the FIPS provider

If the DRBG is used within the scope of the FIPS OSSL_provider_init
function then it attempts to register a thread callback via c_thread_start.
However the implementation of c_thread_start assumed that the provider's
provctx was already present. However because OSSL_provider_init is still
running it was actually NULL. This means the thread callback fail to work
correctly and a memory leak resulted.

Instead of having c_thread_start use the provctx as the callback argument
we change the definition of c_thread_start to have an explicit callback
argument to use.

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15278)
Matt Caswell 2 years ago
parent
commit
c9732f0953
4 changed files with 16 additions and 9 deletions
  1. 10 5
      crypto/initthread.c
  2. 3 2
      crypto/provider_core.c
  3. 1 1
      include/crypto/cryptlib.h
  4. 2 1
      include/openssl/core_dispatch.h

+ 10 - 5
crypto/initthread.c

@@ -237,12 +237,12 @@ void OPENSSL_thread_stop(void)
     }
 }
 
-void ossl_ctx_thread_stop(void *arg)
+void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
 {
     if (destructor_key.sane != -1) {
         THREAD_EVENT_HANDLER **hands
             = init_get_thread_local(&destructor_key.value, 0, 1);
-        init_thread_stop(arg, hands);
+        init_thread_stop(ctx, hands);
     }
 }
 
@@ -285,10 +285,14 @@ static const OSSL_LIB_CTX_METHOD thread_event_ossl_ctx_method = {
     thread_event_ossl_ctx_free,
 };
 
-void ossl_ctx_thread_stop(void *arg)
+static void ossl_arg_thread_stop(void *arg)
+{
+    ossl_ctx_thread_stop((OSSL_LIB_CTX *)arg);
+}
+
+void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
 {
     THREAD_EVENT_HANDLER **hands;
-    OSSL_LIB_CTX *ctx = PROV_LIBCTX_OF(arg);
     CRYPTO_THREAD_LOCAL *local
         = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX,
                                 &thread_event_ossl_ctx_method);
@@ -367,7 +371,8 @@ 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_ctx_thread_stop))
+        if (!c_thread_start(FIPS_get_core_handle(ctx), ossl_arg_thread_stop,
+                            ctx))
             return 0;
     }
 #endif

+ 3 - 2
crypto/provider_core.c

@@ -1603,7 +1603,8 @@ static OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle)
 }
 
 static int core_thread_start(const OSSL_CORE_HANDLE *handle,
-                             OSSL_thread_stop_handler_fn handfn)
+                             OSSL_thread_stop_handler_fn handfn,
+                             void *arg)
 {
     /*
      * We created this object originally and we know it is actually an
@@ -1611,7 +1612,7 @@ static int core_thread_start(const OSSL_CORE_HANDLE *handle,
      */
     OSSL_PROVIDER *prov = (OSSL_PROVIDER *)handle;
 
-    return ossl_init_thread_start(prov, prov->provctx, handfn);
+    return ossl_init_thread_start(prov, arg, handfn);
 }
 
 /*

+ 1 - 1
include/crypto/cryptlib.h

@@ -21,7 +21,7 @@ int ossl_init_thread_start(const void *index, void *arg,
 int ossl_init_thread_deregister(void *index);
 int ossl_init_thread(void);
 void ossl_cleanup_thread(void);
-void ossl_ctx_thread_stop(void *arg);
+void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx);
 
 /*
  * OPENSSL_INIT flags. The primary list of these is in crypto.h. Flags below

+ 2 - 1
include/openssl/core_dispatch.h

@@ -68,7 +68,8 @@ OSSL_CORE_MAKE_FUNC(int,core_get_params,(const OSSL_CORE_HANDLE *prov,
                                          OSSL_PARAM params[]))
 # define OSSL_FUNC_CORE_THREAD_START           3
 OSSL_CORE_MAKE_FUNC(int,core_thread_start,(const OSSL_CORE_HANDLE *prov,
-                                           OSSL_thread_stop_handler_fn handfn))
+                                           OSSL_thread_stop_handler_fn handfn,
+                                           void *arg))
 # define OSSL_FUNC_CORE_GET_LIBCTX             4
 OSSL_CORE_MAKE_FUNC(OPENSSL_CORE_CTX *,core_get_libctx,
                     (const OSSL_CORE_HANDLE *prov))