diff options
author | Matt Caswell <matt@openssl.org> | 2016-04-14 22:28:54 +0200 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2016-04-14 23:15:32 +0200 |
commit | 1ee7b8b97c90e8e59627bfcbda3714f18368a9e1 (patch) | |
tree | 53a54a29d27fbdde8625fbfce8d230255a5fc020 /crypto/ex_data.c | |
parent | Add Haiku support. (diff) | |
download | openssl-1ee7b8b97c90e8e59627bfcbda3714f18368a9e1.tar.xz openssl-1ee7b8b97c90e8e59627bfcbda3714f18368a9e1.zip |
Fix ex_data locks issue
Travis identified a problem with freeing the ex_data locks which wasn't
quite right in ff2344052. Trying to fix it identified a further problem:
the ex_data locks are cleaned up by OPENSSL_cleanup(), which is called
explicitly by CRYPTO_mem_leaks(), but then later the BIO passed to
CRYPTO_mem_leaks() is freed. An attempt is then made to use the ex_data
lock already freed.
Reviewed-by: Tim Hudson <tjh@openssl.org>
Diffstat (limited to 'crypto/ex_data.c')
-rw-r--r-- | crypto/ex_data.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/crypto/ex_data.c b/crypto/ex_data.c index c607f87d65..ca1c204f38 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -134,7 +134,7 @@ typedef struct ex_callbacks_st { static EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT]; -static CRYPTO_RWLOCK *ex_data_lock; +static CRYPTO_RWLOCK *ex_data_lock = NULL; static CRYPTO_ONCE ex_data_init = CRYPTO_ONCE_STATIC_INIT; static void do_ex_data_init(void) @@ -142,12 +142,6 @@ static void do_ex_data_init(void) ex_data_lock = CRYPTO_THREAD_lock_new(); } -void ex_data_cleanup(void) -{ - CRYPTO_THREAD_lock_free(ex_data_lock); - ex_data_lock = NULL; -} - /* * Return the EX_CALLBACKS from the |ex_data| array that corresponds to * a given class. On success, *holds the lock.* @@ -163,6 +157,19 @@ static EX_CALLBACKS *get_and_lock(int class_index) CRYPTO_THREAD_run_once(&ex_data_init, do_ex_data_init); + if (ex_data_lock == NULL) { + /* + * This can happen in normal operation when using CRYPTO_mem_leaks(). + * The CRYPTO_mem_leaks() function calls OPENSSL_cleanup() which cleans + * up the locks. Subsequently the BIO that CRYPTO_mem_leaks() uses gets + * freed, which also attempts to free the ex_data. However + * CRYPTO_mem_leaks() ensures that the ex_data is freed early (i.e. + * before OPENSSL_cleanup() is called), so if we get here we can safely + * ignore this operation. We just treat it as an error. + */ + return NULL; + } + ip = &ex_data[class_index]; CRYPTO_THREAD_write_lock(ex_data_lock); return ip; @@ -189,6 +196,9 @@ void crypto_cleanup_all_ex_data_int(void) sk_EX_CALLBACK_pop_free(ip->meth, cleanup_cb); ip->meth = NULL; } + + CRYPTO_THREAD_lock_free(ex_data_lock); + ex_data_lock = NULL; } |