mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
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)
This commit is contained in:
parent
e1c0348cc7
commit
eb2b989206
@ -603,7 +603,8 @@ static int addrinfo_wrap(int family, int socktype,
|
||||
|
||||
DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init)
|
||||
{
|
||||
OPENSSL_init_crypto(0, NULL);
|
||||
if (!OPENSSL_init_crypto(0, NULL))
|
||||
return 0;
|
||||
bio_lookup_lock = CRYPTO_THREAD_lock_new();
|
||||
return bio_lookup_lock != NULL;
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ CRYPTO_ONCE engine_lock_init = CRYPTO_ONCE_STATIC_INIT;
|
||||
|
||||
DEFINE_RUN_ONCE(do_engine_lock_init)
|
||||
{
|
||||
OPENSSL_init_crypto(0, NULL);
|
||||
if (!OPENSSL_init_crypto(0, NULL))
|
||||
return 0;
|
||||
global_engine_lock = CRYPTO_THREAD_lock_new();
|
||||
return global_engine_lock != NULL;
|
||||
}
|
||||
|
@ -265,11 +265,19 @@ static void ERR_STATE_free(ERR_STATE *s)
|
||||
|
||||
DEFINE_RUN_ONCE_STATIC(do_err_strings_init)
|
||||
{
|
||||
OPENSSL_init_crypto(0, NULL);
|
||||
if (!OPENSSL_init_crypto(0, NULL))
|
||||
return 0;
|
||||
err_string_lock = CRYPTO_THREAD_lock_new();
|
||||
if (err_string_lock == NULL)
|
||||
return 0;
|
||||
int_error_hash = lh_ERR_STRING_DATA_new(err_string_data_hash,
|
||||
err_string_data_cmp);
|
||||
return err_string_lock != NULL && int_error_hash != NULL;
|
||||
if (int_error_hash == NULL) {
|
||||
CRYPTO_THREAD_lock_free(err_string_lock);
|
||||
err_string_lock = NULL;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void err_cleanup(void)
|
||||
@ -662,7 +670,10 @@ DEFINE_RUN_ONCE_STATIC(err_do_init)
|
||||
|
||||
ERR_STATE *ERR_get_state(void)
|
||||
{
|
||||
ERR_STATE *state = NULL;
|
||||
ERR_STATE *state;
|
||||
|
||||
if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
|
||||
return NULL;
|
||||
|
||||
if (!RUN_ONCE(&err_init, err_do_init))
|
||||
return NULL;
|
||||
@ -694,13 +705,41 @@ ERR_STATE *ERR_get_state(void)
|
||||
return state;
|
||||
}
|
||||
|
||||
/*
|
||||
* err_shelve_state returns the current thread local error state
|
||||
* and freezes the error module until err_unshelve_state is called.
|
||||
*/
|
||||
int err_shelve_state(void **state)
|
||||
{
|
||||
if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
|
||||
return 0;
|
||||
|
||||
if (!RUN_ONCE(&err_init, err_do_init))
|
||||
return 0;
|
||||
|
||||
*state = CRYPTO_THREAD_get_local(&err_thread_local);
|
||||
if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* err_unshelve_state restores the error state that was returned
|
||||
* by err_shelve_state previously.
|
||||
*/
|
||||
void err_unshelve_state(void* state)
|
||||
{
|
||||
if (state != (void*)-1)
|
||||
CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)state);
|
||||
}
|
||||
|
||||
int ERR_get_next_error_library(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
|
||||
if (!RUN_ONCE(&err_string_init, do_err_strings_init))
|
||||
return 0;
|
||||
}
|
||||
|
||||
CRYPTO_THREAD_write_lock(err_string_lock);
|
||||
ret = int_err_library_number++;
|
||||
|
@ -37,7 +37,8 @@ static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT;
|
||||
|
||||
DEFINE_RUN_ONCE_STATIC(do_ex_data_init)
|
||||
{
|
||||
OPENSSL_init_crypto(0, NULL);
|
||||
if (!OPENSSL_init_crypto(0, NULL))
|
||||
return 0;
|
||||
ex_data_lock = CRYPTO_THREAD_lock_new();
|
||||
return ex_data_lock != NULL;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ int ossl_init_thread_start(uint64_t opts);
|
||||
* use".
|
||||
*/
|
||||
# define OPENSSL_INIT_ZLIB 0x00010000L
|
||||
# define OPENSSL_INIT_BASE_ONLY 0x00040000L
|
||||
|
||||
/* OPENSSL_INIT_THREAD flags */
|
||||
# define OPENSSL_INIT_THREAD_ASYNC 0x01
|
||||
|
@ -13,5 +13,7 @@
|
||||
int err_load_crypto_strings_int(void);
|
||||
void err_cleanup(void);
|
||||
void err_delete_thread_state(void);
|
||||
int err_shelve_state(void **);
|
||||
void err_unshelve_state(void *);
|
||||
|
||||
#endif
|
||||
|
@ -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);
|
||||
#ifndef OPENSSL_SYS_UEFI
|
||||
atexit(OPENSSL_cleanup);
|
||||
#endif
|
||||
if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL)
|
||||
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
|
||||
if (atexit(OPENSSL_cleanup) != 0)
|
||||
goto err;
|
||||
#endif
|
||||
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)
|
||||
|
@ -141,15 +141,15 @@ CAPI engine (if available). This not a default option.
|
||||
With this option the library will automatically load and initialise the
|
||||
padlock engine (if available). This not a default option.
|
||||
|
||||
=item OPENSSL_INIT_ENGINE_DASYNC
|
||||
=item OPENSSL_INIT_ENGINE_AFALG
|
||||
|
||||
With this option the library will automatically load and initialise the
|
||||
DASYNC engine. This not a default option.
|
||||
AFALG engine. This not a default option.
|
||||
|
||||
=item OPENSSL_INIT_ENGINE_ALL_BUILTIN
|
||||
|
||||
With this option the library will automatically load and initialise all the
|
||||
built in engines listed above with the exception of the openssl and dasync
|
||||
built in engines listed above with the exception of the openssl and afalg
|
||||
engines. This not a default option.
|
||||
|
||||
=item OPENSSL_INIT_ATFORK
|
||||
|
@ -376,8 +376,9 @@ int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len);
|
||||
# define OPENSSL_INIT_ENGINE_CAPI 0x00002000L
|
||||
# define OPENSSL_INIT_ENGINE_PADLOCK 0x00004000L
|
||||
# define OPENSSL_INIT_ENGINE_AFALG 0x00008000L
|
||||
# define OPENSSL_INIT_reserved_internal 0x00010000L
|
||||
/* OPENSSL_INIT_ZLIB 0x00010000L */
|
||||
# define OPENSSL_INIT_ATFORK 0x00020000L
|
||||
/* OPENSSL_INIT_BASE_ONLY 0x00040000L */
|
||||
/* OPENSSL_INIT flag range 0xfff00000 reserved for OPENSSL_init_ssl() */
|
||||
/* Max OPENSSL_INIT flag value is 0x80000000 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user