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/err | |
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/err')
-rw-r--r-- | crypto/err/err.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/crypto/err/err.c b/crypto/err/err.c index f55655c6b6..03cbd738e1 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -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++; |