aboutsummaryrefslogtreecommitdiff
path: root/crypto/ex_data.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2016-04-14 21:28:54 +0100
committerMatt Caswell <matt@openssl.org>2016-04-14 22:15:32 +0100
commit1ee7b8b97c90e8e59627bfcbda3714f18368a9e1 (patch)
tree53a54a29d27fbdde8625fbfce8d230255a5fc020 /crypto/ex_data.c
parent6e08e9e7ccf00aba847351adc3b46b9dae1f114d (diff)
downloadopenssl-1ee7b8b97c90e8e59627bfcbda3714f18368a9e1.zip
openssl-1ee7b8b97c90e8e59627bfcbda3714f18368a9e1.tar.gz
openssl-1ee7b8b97c90e8e59627bfcbda3714f18368a9e1.tar.bz2
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.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index c607f87..ca1c204 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;
}