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ý <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)
This commit is contained in:
Neil Horman
2025-06-20 13:01:39 -04:00
parent 4ed9a38a90
commit 24f0715e00
5 changed files with 45 additions and 21 deletions
+17 -9
View File
@@ -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();
+4 -2
View File
@@ -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
+20 -10
View File
@@ -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)
+2
View File
@@ -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
+2
View File
@@ -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,