]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Allow for reuse of thread_local keys in threads_none
authorNeil Horman <nhorman@openssl.org>
Thu, 5 Jun 2025 12:25:52 +0000 (08:25 -0400)
committerNeil Horman <nhorman@openssl.org>
Fri, 6 Jun 2025 18:13:28 +0000 (14:13 -0400)
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 <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/27775)

(cherry picked from commit b6d01d1b1fef2e98a956b7ba4e8443cf7d916dcb)

crypto/threads_none.c

index 66ef99f497a794d4808cb81ca2c2ffe8868acdec..df7b7535ed57ff84baea947791895680e1e4b1f1 100644 (file)
@@ -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;
 }