[openssl-commits] [openssl] OpenSSL_1_1_0-stable update
Richard Levitte
levitte at openssl.org
Tue Dec 12 17:03:52 UTC 2017
The branch OpenSSL_1_1_0-stable has been updated
via 2717f2b7eb845594271a94969767af2c4521e004 (commit)
from 0aa0e13a6a367dc27bfa59bd2ab1e90645c3158b (commit)
- Log -----------------------------------------------------------------
commit 2717f2b7eb845594271a94969767af2c4521e004
Author: Richard Levitte <levitte at openssl.org>
Date: Tue Dec 12 02:05:38 2017 +0100
Fix leak in ERR_get_state() when OPENSSL_init_crypto() isn't called yet
If OPENSSL_init_crypto() hasn't been called yet when ERR_get_state()
is called, it need to be called early, so the base initialization is
done. On some platforms (those who support DSO functionality and
don't define OPENSSL_USE_NODELETE), that includes a call of
ERR_set_mark(), which calls this function again.
Furthermore, we know that ossl_init_thread_start(), which is called
later in ERR_get_state(), calls OPENSSL_init_crypto(0, NULL), except
that's too late.
Here's what happens without an early call of OPENSSL_init_crypto():
=> ERR_get_state():
=> CRYPTO_THREAD_get_local():
<= NULL;
# no state is found, so it gets allocated.
=> ossl_init_thread_start():
=> OPENSSL_init_crypto():
# Here, base_inited is set to 1
# before ERR_set_mark() call
=> ERR_set_mark():
=> ERR_get_state():
=> CRYPTO_THREAD_get_local():
<= NULL;
# no state is found, so it gets allocated!!!!!
=> ossl_init_thread_start():
=> OPENSSL_init_crypto():
# base_inited is 1,
# so no more init to be done
<= 1
<=
=> CRYPTO_thread_set_local():
<=
<=
<=
<= 1
<=
=> CRYPTO_thread_set_local() # previous value removed!
<=
Result: double allocation, and we have a leak.
By calling the base OPENSSL_init_crypto() early, we get this instead:
=> ERR_get_state():
=> OPENSSL_init_crypto():
# Here, base_inited is set to 1
# before ERR_set_mark() call
=> ERR_set_mark():
=> ERR_get_state():
=> OPENSSL_init_crypto():
# base_inited is 1,
# so no more init to be done
<= 1
=> CRYPTO_THREAD_get_local():
<= NULL;
# no state is found, so it gets allocated
# let's assume we got 0xDEADBEEF
=> ossl_init_thread_start():
=> OPENSSL_init_crypto():
# base_inited is 1,
# so no more init to be done
<= 1
<= 1
=> CRYPTO_thread_set_local():
<=
<=
<=
<= 1
=> CRYPTO_THREAD_get_local():
<= 0xDEADBEEF
<= 0xDEADBEEF
Result: no leak.
Reviewed-by: Rich Salz <rsalz at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4913)
(cherry picked from commit aef84bb4efbddfd95d042f3f5f1d362ed7d4faeb)
-----------------------------------------------------------------------
Summary of changes:
crypto/err/err.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 84eabc1..c439928 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -658,6 +658,14 @@ ERR_STATE *ERR_get_state(void)
if (!RUN_ONCE(&err_init, err_do_init))
return NULL;
+ /*
+ * If base OPENSSL_init_crypto() hasn't been called yet, be sure to call
+ * it now to avoid state to be doubly allocated and thereby leak memory.
+ * Needed on any platform that doesn't define OPENSSL_USE_NODELETE.
+ */
+ if (!OPENSSL_init_crypto(0, NULL))
+ return NULL;
+
state = CRYPTO_THREAD_get_local(&err_thread_local);
if (state == NULL) {
More information about the openssl-commits
mailing list