From 5204726bfe664e3f9a44b32b41af1c5716e47ec3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bodo=20M=C3=B6ller?= Date: Wed, 25 Jul 2001 17:18:02 +0000 Subject: [PATCH] md_rand.c thread safety --- CHANGES | 6 ++++++ crypto/cryptlib.c | 3 ++- crypto/crypto.h | 23 ++++++++++++----------- crypto/rand/md_rand.c | 23 +++++++++++++++++++++-- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 7ec2fc8fc3..0b42bed51c 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,12 @@ always reject numbers >= n. [Bodo Moeller] + *) In crypto/rand/md_rand.c, use a new short-time lock CRYPTO_LOCK_RAND2 + to synchronize access to 'locking_thread'. This is necessary on + systems where access to 'locking_thread' (an 'unsigned long' + variable) is not atomic. + [Bodo Moeller] + *) In crypto/rand/md_rand.c, set 'locking_thread' to current thread's ID *before* setting the 'crypto_lock_rand' flag. The previous code had a race condition if 0 is a valid thread ID. diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index fdb416d598..a98bf89e1b 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -90,6 +90,7 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] = "ssl_sess_cert", "ssl", "rand", + "rand2", "debug_malloc", "BIO", "gethostbyname", @@ -100,7 +101,7 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] = "debug_malloc2", "dso", "dynlock", -#if CRYPTO_NUM_LOCKS != 28 +#if CRYPTO_NUM_LOCKS != 29 # error "Inconsistency between crypto.h and cryptlib.c" #endif }; diff --git a/crypto/crypto.h b/crypto/crypto.h index 09ae4cb89d..1fff49de9c 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -112,17 +112,18 @@ extern "C" { #define CRYPTO_LOCK_SSL_SESS_CERT 15 #define CRYPTO_LOCK_SSL 16 #define CRYPTO_LOCK_RAND 17 -#define CRYPTO_LOCK_MALLOC 18 -#define CRYPTO_LOCK_BIO 19 -#define CRYPTO_LOCK_GETHOSTBYNAME 20 -#define CRYPTO_LOCK_GETSERVBYNAME 21 -#define CRYPTO_LOCK_READDIR 22 -#define CRYPTO_LOCK_RSA_BLINDING 23 -#define CRYPTO_LOCK_DH 24 -#define CRYPTO_LOCK_MALLOC2 25 -#define CRYPTO_LOCK_DSO 26 -#define CRYPTO_LOCK_DYNLOCK 27 -#define CRYPTO_NUM_LOCKS 28 +#define CRYPTO_LOCK_RAND2 18 +#define CRYPTO_LOCK_MALLOC 19 +#define CRYPTO_LOCK_BIO 20 +#define CRYPTO_LOCK_GETHOSTBYNAME 21 +#define CRYPTO_LOCK_GETSERVBYNAME 22 +#define CRYPTO_LOCK_READDIR 23 +#define CRYPTO_LOCK_RSA_BLINDING 24 +#define CRYPTO_LOCK_DH 25 +#define CRYPTO_LOCK_MALLOC2 26 +#define CRYPTO_LOCK_DSO 27 +#define CRYPTO_LOCK_DYNLOCK 28 +#define CRYPTO_NUM_LOCKS 29 #define CRYPTO_LOCK 1 #define CRYPTO_UNLOCK 2 diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c index 0db87d4510..ed56536295 100644 --- a/crypto/rand/md_rand.c +++ b/crypto/rand/md_rand.c @@ -144,6 +144,7 @@ static int initialized=0; static unsigned int crypto_lock_rand = 0; /* may be set only when a thread * holds CRYPTO_LOCK_RAND * (to prevent double locking) */ +/* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */ static unsigned long locking_thread = 0; /* valid iff crypto_lock_rand is set */ @@ -210,7 +211,14 @@ static void ssleay_rand_add(const void *buf, int num, double add) */ /* check if we already have the lock */ - do_not_lock = crypto_lock_rand && (locking_thread == CRYPTO_thread_id()); + if (crypto_lock_rand) + { + CRYPTO_r_lock(CRYPTO_LOCK_RAND2); + do_not_lock = (locking_thread == CRYPTO_thread_id()); + CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); + } + else + do_not_lock = 0; if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND); st_idx=state_index; @@ -361,7 +369,9 @@ static int ssleay_rand_bytes(unsigned char *buf, int num) CRYPTO_w_lock(CRYPTO_LOCK_RAND); /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ + CRYPTO_w_lock(CRYPTO_LOCK_RAND2); locking_thread = CRYPTO_thread_id(); + CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); crypto_lock_rand = 1; if (!initialized) @@ -520,14 +530,23 @@ static int ssleay_rand_status(void) /* check if we already have the lock * (could happen if a RAND_poll() implementation calls RAND_status()) */ - do_not_lock = crypto_lock_rand && (locking_thread == CRYPTO_thread_id()); + if (crypto_lock_rand) + { + CRYPTO_r_lock(CRYPTO_LOCK_RAND2); + do_not_lock = (locking_thread == CRYPTO_thread_id()); + CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); + } + else + do_not_lock = 0; if (!do_not_lock) { CRYPTO_w_lock(CRYPTO_LOCK_RAND); /* prevent ssleay_rand_bytes() from trying to obtain the lock again */ + CRYPTO_w_lock(CRYPTO_LOCK_RAND2); locking_thread = CRYPTO_thread_id(); + CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); crypto_lock_rand = 1; } -- 2.25.1