From: Neil Horman Date: Thu, 12 Jun 2025 17:18:41 +0000 (-0400) Subject: Move thread-event handlers to the new thread-local api X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e74a3045b47ae9db721614fa1283b3e8de46c51;p=thirdparty%2Fopenssl.git 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ý Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/27794) --- diff --git a/crypto/context.c b/crypto/context.c index f15bc3d755e..4c54299851a 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 27b460009e1..ea591dcb897 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 1c181933e02..9e0d13137aa 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 da442f8a86f..8ad542c4d87 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,