]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Don't setup a default context while tearing down private contexts
authorNeil Horman <nhorman@openssl.org>
Wed, 28 Jan 2026 20:25:20 +0000 (15:25 -0500)
committerNeil Horman <nhorman@openssl.org>
Thu, 5 Feb 2026 17:08:03 +0000 (12:08 -0500)
In providers/applications that create custom libctx'es via
OSSL_LIB_CTX_new, its possible, if the default provider has never been
initaialized during the lifetime of the linked libcrypto, that we
actually wind up creating the default libctx when we free the
aforementioned custom libctx via, as an example:

legacy_teardown->
 OSSL_LIB_CTX_free->
  ossl_lib_ctx_is_default->
   get_default_context->
    get_thread_default_context->
     default_context_do_init

While this isn't catastrophic, its needless, and in some cases has the
potential to leak memory (for instance if a provider is loaded and
unloaded repeatedly in an environment in which the provider is linked to
libcrypto.so while the calling application is statically linked to
libcrypto.a

Its also fairly easy to clean up, by adding an internal parameter to
gate the creation of the default libctx on the request of the caller, so
do that here

Fixes openssl/project#1846

Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
MergeDate: Thu Feb  5 17:08:13 2026
(Merged from https://github.com/openssl/openssl/pull/29830)

crypto/context.c
include/internal/cryptlib.h

index c25a0bd6564ef390a27363ebd7104289b9577658..4657d6a0dfab9bad48992e013b4c668a018357c6 100644 (file)
@@ -406,24 +406,24 @@ static int context_deinit(OSSL_LIB_CTX *ctx)
 static OSSL_LIB_CTX default_context_int;
 
 static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
+static CRYPTO_ONCE default_context_thread_key_init = CRYPTO_ONCE_STATIC_INIT;
 static CRYPTO_THREAD_LOCAL default_context_thread_local;
 static int default_context_inited = 0;
 
-DEFINE_RUN_ONCE_STATIC(default_context_do_init)
+DEFINE_RUN_ONCE_STATIC(default_context_do_thread_key_init)
 {
     if (!CRYPTO_THREAD_init_local(&default_context_thread_local, NULL))
-        goto err;
+        return 0;
+    return 1;
+}
 
+DEFINE_RUN_ONCE_STATIC(default_context_do_init)
+{
     if (!context_init(&default_context_int))
-        goto deinit_thread;
+        return 0;
 
     default_context_inited = 1;
     return 1;
-
-deinit_thread:
-    CRYPTO_THREAD_cleanup_local(&default_context_thread_local);
-err:
-    return 0;
 }
 
 void ossl_lib_ctx_default_deinit(void)
@@ -437,12 +437,23 @@ void ossl_lib_ctx_default_deinit(void)
 
 static OSSL_LIB_CTX *get_thread_default_context(void)
 {
+    if (!RUN_ONCE(&default_context_thread_key_init, default_context_do_thread_key_init))
+        return NULL;
+
     if (!RUN_ONCE(&default_context_init, default_context_do_init))
         return NULL;
 
     return CRYPTO_THREAD_get_local(&default_context_thread_local);
 }
 
+static OSSL_LIB_CTX *check_thread_default_context(void)
+{
+    if (!RUN_ONCE(&default_context_thread_key_init, default_context_do_thread_key_init))
+        return NULL;
+
+    return CRYPTO_THREAD_get_local(&default_context_thread_local);
+}
+
 static OSSL_LIB_CTX *get_default_context(void)
 {
     OSSL_LIB_CTX *current_defctx = get_thread_default_context();
@@ -452,6 +463,15 @@ static OSSL_LIB_CTX *get_default_context(void)
     return current_defctx;
 }
 
+static OSSL_LIB_CTX *check_default_context(void)
+{
+    OSSL_LIB_CTX *current_defctx = check_thread_default_context();
+
+    if (current_defctx == NULL && default_context_inited)
+        current_defctx = &default_context_int;
+    return current_defctx;
+}
+
 static int set_default_context(OSSL_LIB_CTX *defctx)
 {
     if (defctx == &default_context_int)
@@ -514,7 +534,7 @@ int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file)
 
 void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx)
 {
-    if (ctx == NULL || ossl_lib_ctx_is_default(ctx))
+    if (ctx == NULL || ossl_lib_ctx_is_default_nocreate(ctx))
         return;
 
 #ifndef FIPS_MODULE
@@ -528,6 +548,9 @@ void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx)
 #ifndef FIPS_MODULE
 OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void)
 {
+    if (!RUN_ONCE(&default_context_thread_key_init, default_context_do_thread_key_init))
+        return NULL;
+
     if (!RUN_ONCE(&default_context_init, default_context_do_init))
         return NULL;
 
@@ -575,6 +598,15 @@ int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx)
     return 0;
 }
 
+int ossl_lib_ctx_is_default_nocreate(OSSL_LIB_CTX *ctx)
+{
+#ifndef FIPS_MODULE
+    if (ctx == NULL || ctx == check_default_context())
+        return 1;
+#endif
+    return 0;
+}
+
 int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx)
 {
 #ifndef FIPS_MODULE
index 6b827dd00801544cf51cb0051d53d5b6270f99ea..625d9d12ef208fe042340c05a641093ed3a539c3 100644 (file)
@@ -122,6 +122,7 @@ typedef struct ossl_ex_data_global_st {
 
 OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx);
 int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx);
+int ossl_lib_ctx_is_default_nocreate(OSSL_LIB_CTX *ctx);
 int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx);
 
 /* Functions to retrieve pointers to data by index */