summaryrefslogtreecommitdiffstats
path: root/crypto/err
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/err
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/err')
-rw-r--r--crypto/err/err.c49
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++;