summaryrefslogtreecommitdiffstats
path: root/crypto/init.c
diff options
context:
space:
mode:
authorBernd Edlinger <bernd.edlinger@hotmail.de>2018-04-20 15:45:06 +0200
committerBernd Edlinger <bernd.edlinger@hotmail.de>2018-04-20 15:45:06 +0200
commiteb2b9892065cf5b69400b98ca82e4e99a525eb29 (patch)
tree0185f809739e7ffbde0ee7d477f749fd34a541ce /crypto/init.c
parente1c0348cc728cb37003ae411879bd23b6a84fcc8 (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.c57
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)