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)
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;
}
#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)
{
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;
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;
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;