diff options
author | Tomas Mraz <tomas@openssl.org> | 2021-08-03 17:29:04 +0200 |
---|---|---|
committer | Pauli <pauli@openssl.org> | 2021-08-05 09:21:00 +1000 |
commit | b5c4dc6ce50b7fcf1b51721a61e1a827d1eb05a3 (patch) | |
tree | 81ae5114fc79a18e068eff17eb5778e9556b7bda | |
parent | 421953effea12b1ce6e2953786a83acc426b2622 (diff) |
Prevent recursive call of OPENSSL_INIT_LOAD_CONFIG
If objects are added in a config file the OPENSSL_INIT_LOAD_CONFIG
will be called recursively which results in hang in RUN_ONCE.
Fixes #16186
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16210)
-rw-r--r-- | crypto/init.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/crypto/init.c b/crypto/init.c index 552a4fa66c..6a27d1a8e4 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -44,6 +44,7 @@ struct ossl_init_stop_st { static OPENSSL_INIT_STOP *stop_handlers = NULL; static CRYPTO_RWLOCK *init_lock = NULL; +static CRYPTO_THREAD_LOCAL in_init_config_local; static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT; static int base_inited = 0; @@ -61,7 +62,10 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) OPENSSL_cpuid_setup(); if (!ossl_init_thread()) - return 0; + goto err; + + if (!CRYPTO_THREAD_init_local(&in_init_config_local, NULL)) + goto err; base_inited = 1; return 1; @@ -366,6 +370,8 @@ void OPENSSL_cleanup(void) CRYPTO_THREAD_lock_free(init_lock); init_lock = NULL; + CRYPTO_THREAD_cleanup_local(&in_init_config_local); + /* * We assume we are single-threaded for this function, i.e. no race * conditions for the various "*_inited" vars below. @@ -566,22 +572,29 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; if (opts & OPENSSL_INIT_LOAD_CONFIG) { - int ret; + int loading = CRYPTO_THREAD_get_local(&in_init_config_local) != NULL; - if (settings == NULL) { - ret = RUN_ONCE(&config, ossl_init_config); - } else { - if (!CRYPTO_THREAD_write_lock(init_lock)) + /* If called recursively from OBJ_ calls, just skip it. */ + if (!loading) { + int ret; + + if (!CRYPTO_THREAD_set_local(&in_init_config_local, (void *)-1)) + return 0; + if (settings == NULL) { + ret = RUN_ONCE(&config, ossl_init_config); + } else { + if (!CRYPTO_THREAD_write_lock(init_lock)) + return 0; + conf_settings = settings; + ret = RUN_ONCE_ALT(&config, ossl_init_config_settings, + ossl_init_config); + conf_settings = NULL; + CRYPTO_THREAD_unlock(init_lock); + } + + if (ret <= 0) return 0; - conf_settings = settings; - ret = RUN_ONCE_ALT(&config, ossl_init_config_settings, - ossl_init_config); - conf_settings = NULL; - CRYPTO_THREAD_unlock(init_lock); } - - if (ret <= 0) - return 0; } if ((opts & OPENSSL_INIT_ASYNC) |