From: Neil Horman Date: Thu, 5 Jun 2025 12:25:52 +0000 (-0400) Subject: Allow for reuse of thread_local keys in threads_none X-Git-Tag: openssl-3.5.1~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=acadfec4cf83db616914b3fd88dcc402cdfbc18a;p=thirdparty%2Fopenssl.git Allow for reuse of thread_local keys in threads_none If openssl is configured with no-threads, the implementation has a hard limit of 256 LIB_CTX values, as each LIB_CTX allocates a thread local key, and we never reuse them (like libc does when using pthread_key_create/destroy. Improve the situation by allowing for marking freed keys as unsued and searching for an available key when allocating Fixes #27757 Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell Reviewed-by: Saša Nedvědický (Merged from https://github.com/openssl/openssl/pull/27775) (cherry picked from commit b6d01d1b1fef2e98a956b7ba4e8443cf7d916dcb) --- diff --git a/crypto/threads_none.c b/crypto/threads_none.c index 240b7d9fdcf..ef1a757bce6 100644 --- a/crypto/threads_none.c +++ b/crypto/threads_none.c @@ -153,18 +153,28 @@ int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) # define OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX 256 -static void *thread_local_storage[OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX]; +struct thread_local_storage_entry { + void *data; + uint8_t used; +}; + +static struct thread_local_storage_entry thread_local_storage[OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX]; int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) { - static unsigned int thread_local_key = 0; + int entry_idx = 0; - if (thread_local_key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) - return 0; + for (entry_idx = 0; entry_idx < OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX; entry_idx++) { + if (!thread_local_storage[entry_idx].used) + break; + } - *key = thread_local_key++; + if (entry_idx == OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) + return 0; - thread_local_storage[*key] = NULL; + *key = entry_idx; + thread_local_storage[*key].used = 1; + thread_local_storage[*key].data = NULL; return 1; } @@ -174,7 +184,7 @@ void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) return NULL; - return thread_local_storage[*key]; + return thread_local_storage[*key].data; } int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) @@ -182,13 +192,18 @@ int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) return 0; - thread_local_storage[*key] = val; + thread_local_storage[*key].data = val; return 1; } int CRYPTO_THREAD_cleanup_local(CRYPTO_THREAD_LOCAL *key) { + if (*key >= OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX) + return 0; + + thread_local_storage[*key].used = 0; + thread_local_storage[*key].data = NULL; *key = OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX + 1; return 1; }