From: Neil Horman Date: Tue, 17 Jun 2025 15:49:54 +0000 (-0400) Subject: Allow for differentiating between default and NULL context X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=24f0715e00a6ec1d33cf9bc602444b465bafcbb6;p=thirdparty%2Fopenssl.git Allow for differentiating between default and NULL context Allow for use of default context in the thread-local api by using get_concrete This creates a problem however in that get_concrete access a thread-local api, creating a recursive call that exhausts stack space So create a special context token that identifys the no context use case when we want to store thread-local data without an explicit context index 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/async/async.c b/crypto/async/async.c index c23027e3aef..447c7976109 100644 --- a/crypto/async/async.c +++ b/crypto/async/async.c @@ -44,7 +44,8 @@ static async_ctx *async_ctx_new(void) async_fibre_init_dispatcher(&nctx->dispatcher); nctx->currjob = NULL; nctx->blocked = 0; - if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_CTX_KEY, NULL, nctx)) + if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_CTX_KEY, + CRYPTO_THREAD_NO_CONTEXT, nctx)) goto err; return nctx; @@ -56,7 +57,8 @@ err: async_ctx *async_get_ctx(void) { - return (async_ctx *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_CTX_KEY, NULL); + return (async_ctx *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_CTX_KEY, + CRYPTO_THREAD_NO_CONTEXT); } static int async_ctx_free(void) @@ -65,7 +67,8 @@ static int async_ctx_free(void) ctx = async_get_ctx(); - if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_CTX_KEY, NULL, NULL)) + if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_CTX_KEY, + CRYPTO_THREAD_NO_CONTEXT, NULL)) return 0; OPENSSL_free(ctx); @@ -99,7 +102,8 @@ static ASYNC_JOB *async_get_pool_job(void) { ASYNC_JOB *job; async_pool *pool; - pool = (async_pool *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, NULL); + pool = (async_pool *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, + CRYPTO_THREAD_NO_CONTEXT); if (pool == NULL) { /* * Pool has not been initialised, so init with the defaults, i.e. @@ -107,7 +111,8 @@ static ASYNC_JOB *async_get_pool_job(void) { */ if (ASYNC_init_thread(0, 0) == 0) return NULL; - pool = (async_pool *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, NULL); + pool = (async_pool *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, + CRYPTO_THREAD_NO_CONTEXT); } job = sk_ASYNC_JOB_pop(pool->jobs); @@ -131,7 +136,8 @@ static ASYNC_JOB *async_get_pool_job(void) { static void async_release_job(ASYNC_JOB *job) { async_pool *pool; - pool = (async_pool *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, NULL); + pool = (async_pool *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, + CRYPTO_THREAD_NO_CONTEXT); if (pool == NULL) { ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); return; @@ -379,7 +385,8 @@ int ASYNC_init_thread(size_t max_size, size_t init_size) curr_size++; } pool->curr_size = curr_size; - if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, NULL, pool)) { + if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, + CRYPTO_THREAD_NO_CONTEXT, pool)) { ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SET_POOL); goto err; } @@ -395,13 +402,14 @@ err: static void async_delete_thread_state(void *arg) { async_pool *pool = (async_pool *)CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, - NULL); + CRYPTO_THREAD_NO_CONTEXT); if (pool != NULL) { async_empty_pool(pool); sk_ASYNC_JOB_free(pool->jobs); OPENSSL_free(pool); - CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, NULL, NULL); + CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ASYNC_POOL_KEY, + CRYPTO_THREAD_NO_CONTEXT, NULL); } async_local_cleanup(); async_ctx_free(); diff --git a/crypto/context.c b/crypto/context.c index 4c54299851a..32f80cf5220 100644 --- a/crypto/context.c +++ b/crypto/context.c @@ -402,7 +402,8 @@ 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_ex(CRYPTO_THREAD_LOCAL_DEF_CTX_KEY, NULL); + return CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_DEF_CTX_KEY, + CRYPTO_THREAD_NO_CONTEXT); } static OSSL_LIB_CTX *get_default_context(void) @@ -419,7 +420,8 @@ static int set_default_context(OSSL_LIB_CTX *defctx) if (defctx == &default_context_int) defctx = NULL; - return CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_DEF_CTX_KEY, NULL, defctx); + return CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_DEF_CTX_KEY, + CRYPTO_THREAD_NO_CONTEXT, defctx); } #endif diff --git a/crypto/err/err.c b/crypto/err/err.c index 8b06848e88f..485e802f96a 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -638,12 +638,14 @@ const char *ERR_reason_error_string(unsigned long e) static void err_delete_thread_state(void *unused) { - ERR_STATE *state = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL); + ERR_STATE *state = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT); if (state == NULL) return; - CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL, NULL); + CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT, NULL); OSSL_ERR_STATE_free(state); } @@ -667,24 +669,29 @@ ERR_STATE *ossl_err_get_state_int(void) if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL)) return NULL; - state = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL); + state = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT); if (state == (ERR_STATE *)-1) return NULL; if (state == NULL) { - if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL, (ERR_STATE *)-1)) + if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT, (ERR_STATE *)-1)) return NULL; state = OSSL_ERR_STATE_new(); if (state == NULL) { - CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL, NULL); + CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT, NULL); return NULL; } if (!ossl_init_thread_start(NULL, NULL, err_delete_thread_state) - || !CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL, state)) { + || !CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT, state)) { OSSL_ERR_STATE_free(state); - CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL, NULL); + CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT, NULL); return NULL; } @@ -727,8 +734,10 @@ int err_shelve_state(void **state) if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL)) return 0; - *state = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL); - if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL, (ERR_STATE *)-1)) + *state = CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT); + if (!CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT, (ERR_STATE *)-1)) return 0; set_sys_error(saveerrno); @@ -742,7 +751,8 @@ int err_shelve_state(void **state) void err_unshelve_state(void* state) { if (state != (void*)-1) - CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, NULL, (ERR_STATE *)state); + CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_ERR_KEY, + CRYPTO_THREAD_NO_CONTEXT, (ERR_STATE *)state); } int ERR_get_next_error_library(void) diff --git a/crypto/threads_common.c b/crypto/threads_common.c index d5ef08413da..fdd19418a82 100644 --- a/crypto/threads_common.c +++ b/crypto/threads_common.c @@ -256,6 +256,7 @@ void *CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_KEY_ID id, OSSL_LIB_CTX *ct MASTER_KEY_ENTRY *mkey; CTX_TABLE_ENTRY ctxd; + ctx = (ctx == CRYPTO_THREAD_NO_CONTEXT) ? NULL : ossl_lib_ctx_get_concrete(ctx); /* * Make sure the master key has been initialized * NOTE: We use CRYPTO_THREAD_run_once here, rather than the @@ -333,6 +334,7 @@ int CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_KEY_ID id, { MASTER_KEY_ENTRY *mkey; + ctx = (ctx == CRYPTO_THREAD_NO_CONTEXT) ? NULL : ossl_lib_ctx_get_concrete(ctx); /* * Make sure our master key is initialized * See notes above on the use of CRYPTO_THREAD_run_once here diff --git a/include/internal/threads_common.h b/include/internal/threads_common.h index 21785471afc..4b949fe956c 100644 --- a/include/internal/threads_common.h +++ b/include/internal/threads_common.h @@ -22,6 +22,8 @@ typedef enum { CRYPTO_THREAD_LOCAL_KEY_MAX } CRYPTO_THREAD_LOCAL_KEY_ID; +#define CRYPTO_THREAD_NO_CONTEXT (void *)1 + void *CRYPTO_THREAD_get_local_ex(CRYPTO_THREAD_LOCAL_KEY_ID id, OSSL_LIB_CTX *ctx); int CRYPTO_THREAD_set_local_ex(CRYPTO_THREAD_LOCAL_KEY_ID id,