]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
ensure destructor key is created prior to any other thread specific key
authorNeil Horman <nhorman@openssl.org>
Thu, 20 Nov 2025 16:49:19 +0000 (11:49 -0500)
committerNeil Horman <nhorman@openssl.org>
Mon, 1 Dec 2025 18:32:15 +0000 (13:32 -0500)
https://github.com/openssl/openssl/issues/29077 found that, in the event
that a pthread key is created prior to the destructor_key, glibc will
NULL-ify any thread specific data before the init_thread_destructor
runs, leading to leaks.

Ensure that we always create the destructor key prior to any other
thread local storage keys

Fixes #29907

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Norbert Pocs <norbertp@openssl.org>
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/29182)

(cherry picked from commit 66f92cfb925e5c4c830ab65cf738ab49c5e553a4)

crypto/initthread.c
crypto/threads_none.c
crypto/threads_pthread.c
crypto/threads_win.c

index 07f0cc1c5fe781871aa375866b11272d84549a12..86130345e958ce08dddbfcdac9abf6a3d8c7c418 100644 (file)
@@ -236,12 +236,27 @@ static void init_thread_destructor(void *hands)
     OPENSSL_free(hands);
 }
 
-int ossl_init_thread(void)
+static CRYPTO_ONCE ossl_init_thread_runonce = CRYPTO_ONCE_STATIC_INIT;
+static CRYPTO_THREAD_ID recursion_guard = (CRYPTO_THREAD_ID)-1;
+
+DEFINE_RUN_ONCE_STATIC(ossl_init_thread_once)
 {
+    recursion_guard = CRYPTO_THREAD_get_current_id();
     if (!CRYPTO_THREAD_init_local(&destructor_key.value,
                                   init_thread_destructor))
         return 0;
 
+    recursion_guard = (CRYPTO_THREAD_ID)0;
+    return 1;
+}
+
+int ossl_init_thread(void)
+{
+    if (CRYPTO_THREAD_compare_id(recursion_guard,
+                                 CRYPTO_THREAD_get_current_id()))
+        return 1;
+    if (!RUN_ONCE(&ossl_init_thread_runonce, ossl_init_thread_once))
+        return 0;
     return 1;
 }
 
index 04bc4f1d7d239bdd87d78eb8e467c66c8c6fd517..4e0d8634aa89274b5698bb040386390eaf51463a 100644 (file)
@@ -10,6 +10,7 @@
 #include <openssl/crypto.h>
 #include "internal/cryptlib.h"
 #include "internal/rcu.h"
+#include "crypto/cryptlib.h"
 #include "rcu_internal.h"
 
 #if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
@@ -164,6 +165,11 @@ int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
 {
     int entry_idx = 0;
 
+# ifndef FIPS_MODULE
+    if (!ossl_init_thread())
+        return 0;
+# endif
+
     for (entry_idx = 0; entry_idx < OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX; entry_idx++) {
         if (!thread_local_storage[entry_idx].used)
             break;
index 9d9958e68fe0c6abe77d894a6b5db4db2dad3040..c516fc340a6566d77d6b4783a940a601909f44aa 100644 (file)
@@ -980,6 +980,12 @@ int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
 
 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
 {
+
+# ifndef FIPS_MODULE
+    if (!ossl_init_thread())
+        return 0;
+# endif
+
     if (pthread_key_create(key, cleanup) != 0)
         return 0;
 
index 11029ea0c0bc6527df931042e6eed3e33897b9fd..a83b9e55704640b3b32abfd4343fa1d76f63e691 100644 (file)
@@ -556,6 +556,12 @@ int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void))
 
 int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *))
 {
+
+# ifndef FIPS_MODULE
+    if (!ossl_init_thread())
+        return 0;
+# endif
+
     *key = TlsAlloc();
     if (*key == TLS_OUT_OF_INDEXES)
         return 0;