diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2018-04-20 15:45:06 +0200 |
---|---|---|
committer | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2018-04-20 15:45:06 +0200 |
commit | eb2b9892065cf5b69400b98ca82e4e99a525eb29 (patch) | |
tree | 0185f809739e7ffbde0ee7d477f749fd34a541ce /crypto/init.c | |
parent | e1c0348cc728cb37003ae411879bd23b6a84fcc8 (diff) |
Ensure the thread keys are always allocated in the same order
Fixes: #5899
Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5911)
Diffstat (limited to 'crypto/init.c')
-rw-r--r-- | crypto/init.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/crypto/init.c b/crypto/init.c index c79c32c17a..fb7e3ace87 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -81,22 +81,36 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) * We use a dummy thread local key here. We use the destructor to detect * when the thread is going to stop (where that feature is available) */ - CRYPTO_THREAD_init_local(&threadstopkey, ossl_init_thread_stop_wrap); + if (!CRYPTO_THREAD_init_local(&threadstopkey, ossl_init_thread_stop_wrap)) + return 0; + if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) + goto err; #ifndef OPENSSL_SYS_UEFI - atexit(OPENSSL_cleanup); + if (atexit(OPENSSL_cleanup) != 0) + goto err; #endif - if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) - return 0; OPENSSL_cpuid_setup(); - /* - * BIG FAT WARNING! - * Everything needed to be initialized in this function before threads - * come along MUST happen before base_inited is set to 1, or we will - * see race conditions. - */ base_inited = 1; + return 1; +err: +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_base not ok!\n"); +#endif + CRYPTO_THREAD_lock_free(init_lock); + init_lock = NULL; + + CRYPTO_THREAD_cleanup_local(&threadstopkey); + return 0; +} + +static CRYPTO_ONCE load_crypto_nodelete = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete) +{ +#ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_nodelete()\n"); +#endif #if !defined(OPENSSL_NO_DSO) && !defined(OPENSSL_USE_NODELETE) # ifdef DSO_WIN32 { @@ -108,6 +122,10 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) | GET_MODULE_HANDLE_EX_FLAG_PIN, (void *)&base_inited, &handle); +# ifdef OPENSSL_INIT_DEBUG + fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n", + (ret == TRUE ? "No!" : "Yes.")); +# endif return (ret == TRUE) ? 1 : 0; } # else @@ -116,9 +134,12 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) * to remain loaded until the atexit() handler is run at process exit. */ { - DSO *dso = NULL; + DSO *dso; + void *err; + + if (!err_shelve_state(&err)) + return 0; - ERR_set_mark(); dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE); # ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n", @@ -130,7 +151,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) */ # endif DSO_free(dso); - ERR_pop_to_mark(); + err_unshelve_state(err); } # endif #endif @@ -541,11 +562,17 @@ void OPENSSL_cleanup(void) int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) { if (stopped) { - CRYPTOerr(CRYPTO_F_OPENSSL_INIT_CRYPTO, ERR_R_INIT_FAIL); + if (!(opts & OPENSSL_INIT_BASE_ONLY)) + CRYPTOerr(CRYPTO_F_OPENSSL_INIT_CRYPTO, ERR_R_INIT_FAIL); return 0; } - if (!base_inited && !RUN_ONCE(&base, ossl_init_base)) + if (!RUN_ONCE(&base, ossl_init_base)) + return 0; + + if (!(opts & OPENSSL_INIT_BASE_ONLY) + && !RUN_ONCE(&load_crypto_nodelete, + ossl_init_load_crypto_nodelete)) return 0; if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS) |