Commit 2e74a3045b for openssl.org
commit 2e74a3045b47ae9db721614fa1283b3e8de46c51
Author: Neil Horman <nhorman@openssl.org>
Date: Thu Jun 12 13:18:41 2025 -0400
Move thread-event handlers to the new thread-local api
Thread event handlers in the fips provider create a thread-local storage
key per context, meaning we can exhaust our thread-local space quickly
by creating lots of contexts. Avoid that by moving to the new
thread-local storage api.
Reviewed-by: Saša NedvÄ›dický <sashan@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/27794)
diff --git a/crypto/context.c b/crypto/context.c
index f15bc3d755..4c54299851 100644
--- a/crypto/context.c
+++ b/crypto/context.c
@@ -16,6 +16,7 @@
#include "internal/core.h"
#include "internal/bio.h"
#include "internal/provider.h"
+#include "internal/threads_common.h"
#include "crypto/decoder.h"
#include "crypto/context.h"
@@ -31,7 +32,6 @@ struct ossl_lib_ctx_st {
void *global_properties;
void *drbg;
void *drbg_nonce;
- CRYPTO_THREAD_LOCAL rcu_local_key;
#ifndef FIPS_MODULE
void *provider_conf;
void *bio_core;
@@ -47,7 +47,6 @@ struct ossl_lib_ctx_st {
void *threads;
#endif
#ifdef FIPS_MODULE
- void *thread_event_handler;
void *fips_prov;
#endif
STACK_OF(SSL_COMP) *comp_methods;
@@ -92,9 +91,6 @@ static int context_init(OSSL_LIB_CTX *ctx)
{
int exdata_done = 0;
- if (!CRYPTO_THREAD_init_local(&ctx->rcu_local_key, NULL))
- return 0;
-
ctx->lock = CRYPTO_THREAD_lock_new();
if (ctx->lock == NULL)
goto err;
@@ -187,8 +183,7 @@ static int context_init(OSSL_LIB_CTX *ctx)
#endif
#ifdef FIPS_MODULE
- ctx->thread_event_handler = ossl_thread_event_ctx_new(ctx);
- if (ctx->thread_event_handler == NULL)
+ if (!ossl_thread_event_ctx_new(ctx))
goto err;
ctx->fips_prov = ossl_fips_prov_ossl_ctx_new(ctx);
@@ -226,7 +221,6 @@ static int context_init(OSSL_LIB_CTX *ctx)
ossl_crypto_cleanup_all_ex_data_int(ctx);
CRYPTO_THREAD_lock_free(ctx->lock);
- CRYPTO_THREAD_cleanup_local(&ctx->rcu_local_key);
memset(ctx, '\0', sizeof(*ctx));
return 0;
}
@@ -331,10 +325,7 @@ static void context_deinit_objs(OSSL_LIB_CTX *ctx)
#endif
#ifdef FIPS_MODULE
- if (ctx->thread_event_handler != NULL) {
- ossl_thread_event_ctx_free(ctx->thread_event_handler);
- ctx->thread_event_handler = NULL;
- }
+ ossl_thread_event_ctx_free(ctx);
if (ctx->fips_prov != NULL) {
ossl_fips_prov_ossl_ctx_free(ctx->fips_prov);
@@ -379,7 +370,6 @@ static int context_deinit(OSSL_LIB_CTX *ctx)
CRYPTO_THREAD_lock_free(ctx->lock);
ctx->lock = NULL;
- CRYPTO_THREAD_cleanup_local(&ctx->rcu_local_key);
return 1;
}
@@ -388,24 +378,15 @@ 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_THREAD_LOCAL default_context_thread_local;
static int default_context_inited = 0;
DEFINE_RUN_ONCE_STATIC(default_context_do_init)
{
- if (!CRYPTO_THREAD_init_local(&default_context_thread_local, NULL))
- goto err;
-
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)
@@ -413,7 +394,6 @@ void ossl_lib_ctx_default_deinit(void)
if (!default_context_inited)
return;
context_deinit(&default_context_int);
- CRYPTO_THREAD_cleanup_local(&default_context_thread_local);
default_context_inited = 0;
}
@@ -422,7 +402,7 @@ static OSSL_LIB_CTX *get_thread_default_context(void)
if (!RUN_ONCE(&default_context_init, default_context_do_init))
return NULL;
- return CRYPTO_THREAD_get_local(&default_context_thread_local);
+ return CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_DEF_CTX_KEY, NULL);
}
static OSSL_LIB_CTX *get_default_context(void)
@@ -439,7 +419,7 @@ static int set_default_context(OSSL_LIB_CTX *defctx)
if (defctx == &default_context_int)
defctx = NULL;
- return CRYPTO_THREAD_set_local(&default_context_thread_local, defctx);
+ return CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_DEF_CTX_KEY, NULL, defctx);
}
#endif
@@ -615,9 +595,6 @@ void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index)
#endif
#ifdef FIPS_MODULE
- case OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX:
- return ctx->thread_event_handler;
-
case OSSL_LIB_CTX_FIPS_PROV_INDEX:
return ctx->fips_prov;
#endif
@@ -656,14 +633,6 @@ const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx)
#endif
}
-CRYPTO_THREAD_LOCAL *ossl_lib_ctx_get_rcukey(OSSL_LIB_CTX *libctx)
-{
- libctx = ossl_lib_ctx_get_concrete(libctx);
- if (libctx == NULL)
- return NULL;
- return &libctx->rcu_local_key;
-}
-
int OSSL_LIB_CTX_get_conf_diagnostics(OSSL_LIB_CTX *libctx)
{
libctx = ossl_lib_ctx_get_concrete(libctx);
diff --git a/crypto/initthread.c b/crypto/initthread.c
index 27b460009e..ea591dcb89 100644
--- a/crypto/initthread.c
+++ b/crypto/initthread.c
@@ -12,6 +12,7 @@
#include "crypto/cryptlib.h"
#include "prov/providercommon.h"
#include "internal/thread_once.h"
+#include "internal/threads_common.h"
#include "crypto/context.h"
#ifdef FIPS_MODULE
@@ -90,6 +91,7 @@ static int init_thread_deregister(void *arg, int all);
#endif
static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands);
+#ifndef FIPS_MODULE
static THREAD_EVENT_HANDLER **
init_get_thread_local(CRYPTO_THREAD_LOCAL *local, int alloc, int keep)
{
@@ -106,13 +108,11 @@ init_get_thread_local(CRYPTO_THREAD_LOCAL *local, int alloc, int keep)
return NULL;
}
-#ifndef FIPS_MODULE
if (!init_thread_push_handlers(hands)) {
CRYPTO_THREAD_set_local(local, NULL);
OPENSSL_free(hands);
return NULL;
}
-#endif
}
} else if (!keep) {
CRYPTO_THREAD_set_local(local, NULL);
@@ -121,6 +121,32 @@ init_get_thread_local(CRYPTO_THREAD_LOCAL *local, int alloc, int keep)
return hands;
}
+#else
+static THREAD_EVENT_HANDLER **
+init_get_thread_local_ex(OSSL_LIB_CTX *ctx, int alloc, int keep)
+{
+ THREAD_EVENT_HANDLER **hands = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_TEVENT_KEY, ctx);
+
+ if (alloc) {
+ if (hands == NULL) {
+
+ if ((hands = OPENSSL_zalloc(sizeof(*hands))) == NULL)
+ return NULL;
+
+ if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_TEVENT_KEY, ctx, hands)) {
+ OPENSSL_free(hands);
+ return NULL;
+ }
+ }
+ } else if (!keep) {
+ CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_TEVENT_KEY, ctx, NULL);
+ }
+
+ return hands;
+}
+
+#endif
+
#ifndef FIPS_MODULE
/*
* Since per-thread-specific-data destructors are not universally
@@ -258,22 +284,15 @@ int ossl_thread_register_fips(OSSL_LIB_CTX *libctx)
libctx);
}
-void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx)
+int ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx)
{
THREAD_EVENT_HANDLER **hands = NULL;
- CRYPTO_THREAD_LOCAL *tlocal = OPENSSL_zalloc(sizeof(*tlocal));
-
- if (tlocal == NULL)
- return NULL;
-
- if (!CRYPTO_THREAD_init_local(tlocal, NULL))
- goto deinit;
hands = OPENSSL_zalloc(sizeof(*hands));
if (hands == NULL)
goto err;
- if (!CRYPTO_THREAD_set_local(tlocal, hands))
+ if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_TEVENT_KEY, libctx, hands))
goto err;
/*
@@ -286,19 +305,15 @@ void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx)
* function.
*/
- return tlocal;
+ return 1;
err:
OPENSSL_free(hands);
- CRYPTO_THREAD_cleanup_local(tlocal);
- deinit:
- OPENSSL_free(tlocal);
- return NULL;
+ return 0;
}
-void ossl_thread_event_ctx_free(void *tlocal)
+void ossl_thread_event_ctx_free(OSSL_LIB_CTX *ctx)
{
- CRYPTO_THREAD_cleanup_local(tlocal);
- OPENSSL_free(tlocal);
+ CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_TEVENT_KEY, ctx, NULL);
}
static void ossl_arg_thread_stop(void *arg)
@@ -309,12 +324,8 @@ static void ossl_arg_thread_stop(void *arg)
void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
{
THREAD_EVENT_HANDLER **hands;
- CRYPTO_THREAD_LOCAL *local
- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX);
- if (local == NULL)
- return;
- hands = init_get_thread_local(local, 0, 0);
+ hands = init_get_thread_local_ex(ctx, 0, 0);
init_thread_stop(ctx, hands);
OPENSSL_free(hands);
}
@@ -377,8 +388,7 @@ int ossl_init_thread_start(const void *index, void *arg,
* of OSSL_LIB_CTX and thread. This is because in FIPS mode each
* OSSL_LIB_CTX gets informed about thread stop events individually.
*/
- CRYPTO_THREAD_LOCAL *local
- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX);
+ hands = init_get_thread_local_ex(ctx, 1, 0);
#else
/*
* Outside of FIPS mode the list of THREAD_EVENT_HANDLERs is unique per
@@ -387,9 +397,9 @@ int ossl_init_thread_start(const void *index, void *arg,
* OSSL_LIB_CTXs are informed.
*/
CRYPTO_THREAD_LOCAL *local = &destructor_key.value;
+ hands = init_get_thread_local(local, 1, 0);
#endif
- hands = init_get_thread_local(local, 1, 0);
if (hands == NULL)
return 0;
diff --git a/include/crypto/context.h b/include/crypto/context.h
index 1c181933e0..9e0d13137a 100644
--- a/include/crypto/context.h
+++ b/include/crypto/context.h
@@ -23,7 +23,7 @@ void *ossl_self_test_set_callback_new(OSSL_LIB_CTX *);
void *ossl_indicator_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 *);
+int ossl_thread_event_ctx_new(OSSL_LIB_CTX *);
void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *);
#if defined(OPENSSL_THREADS)
void *ossl_threads_ctx_new(OSSL_LIB_CTX *);
@@ -42,7 +42,7 @@ void ossl_prov_drbg_nonce_ctx_free(void *);
void ossl_indicator_set_callback_free(void *cb);
void ossl_self_test_set_callback_free(void *);
void ossl_rand_crng_ctx_free(void *);
-void ossl_thread_event_ctx_free(void *);
+void ossl_thread_event_ctx_free(OSSL_LIB_CTX *);
void ossl_fips_prov_ossl_ctx_free(void *);
void ossl_release_default_drbg_ctx(void);
#if defined(OPENSSL_THREADS)
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
index da442f8a86..8ad542c4d8 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -103,9 +103,9 @@ typedef struct ossl_ex_data_global_st {
# define OSSL_LIB_CTX_DRBG_INDEX 5
# define OSSL_LIB_CTX_DRBG_NONCE_INDEX 6
/* slot 7 unused, was CRNG test data and can be reused */
-# ifdef FIPS_MODULE
-# define OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX 8
-# endif
+/*
+ * slot 8 unused, was OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX
+ */
# define OSSL_LIB_CTX_FIPS_PROV_INDEX 9
# define OSSL_LIB_CTX_ENCODER_STORE_INDEX 10
# define OSSL_LIB_CTX_DECODER_STORE_INDEX 11
@@ -133,7 +133,6 @@ void ossl_lib_ctx_default_deinit(void);
OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx);
const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx);
-CRYPTO_THREAD_LOCAL *ossl_lib_ctx_get_rcukey(OSSL_LIB_CTX *libctx);
OSSL_LIB_CTX *ossl_crypto_ex_data_get_ossl_lib_ctx(const CRYPTO_EX_DATA *ad);
int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj,