md_rand.c thread safety

This commit is contained in:
Bodo Möller 2001-07-25 17:17:24 +00:00
parent 24cff6ced5
commit daba492c3a
4 changed files with 45 additions and 18 deletions

10
CHANGES
View File

@ -8,8 +8,8 @@
and OpenSSL 0.9.7 were developped in parallel, based on OpenSSL 0.9.6. and OpenSSL 0.9.7 were developped in parallel, based on OpenSSL 0.9.6.
Change log entries are tagged as follows: Change log entries are tagged as follows:
-) applies to 0.9.6a/0.9.6b only -) applies to 0.9.6a/0.9.6b/0.9.6c only
*) applies to 0.9.6a/0.9.6b and 0.9.7 *) applies to 0.9.6a/0.9.6b/0.9.6c and 0.9.7
+) applies to 0.9.7 only +) applies to 0.9.7 only
*) In *) In
@ -24,6 +24,12 @@
always reject numbers >= n. always reject numbers >= n.
[Bodo Moeller] [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 *) 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 *before* setting the 'crypto_lock_rand' flag. The previous code had
a race condition if 0 is a valid thread ID. a race condition if 0 is a valid thread ID.

View File

@ -90,6 +90,7 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] =
"ssl_sess_cert", "ssl_sess_cert",
"ssl", "ssl",
"rand", "rand",
"rand2",
"debug_malloc", "debug_malloc",
"BIO", "BIO",
"gethostbyname", "gethostbyname",
@ -102,7 +103,7 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] =
"dynlock", "dynlock",
"engine", "engine",
"ui", "ui",
#if CRYPTO_NUM_LOCKS != 30 #if CRYPTO_NUM_LOCKS != 31
# error "Inconsistency between crypto.h and cryptlib.c" # error "Inconsistency between crypto.h and cryptlib.c"
#endif #endif
}; };

View File

@ -113,19 +113,20 @@ extern "C" {
#define CRYPTO_LOCK_SSL_SESS_CERT 15 #define CRYPTO_LOCK_SSL_SESS_CERT 15
#define CRYPTO_LOCK_SSL 16 #define CRYPTO_LOCK_SSL 16
#define CRYPTO_LOCK_RAND 17 #define CRYPTO_LOCK_RAND 17
#define CRYPTO_LOCK_MALLOC 18 #define CRYPTO_LOCK_RAND2 18
#define CRYPTO_LOCK_BIO 19 #define CRYPTO_LOCK_MALLOC 19
#define CRYPTO_LOCK_GETHOSTBYNAME 20 #define CRYPTO_LOCK_BIO 20
#define CRYPTO_LOCK_GETSERVBYNAME 21 #define CRYPTO_LOCK_GETHOSTBYNAME 21
#define CRYPTO_LOCK_READDIR 22 #define CRYPTO_LOCK_GETSERVBYNAME 22
#define CRYPTO_LOCK_RSA_BLINDING 23 #define CRYPTO_LOCK_READDIR 23
#define CRYPTO_LOCK_DH 24 #define CRYPTO_LOCK_RSA_BLINDING 24
#define CRYPTO_LOCK_MALLOC2 25 #define CRYPTO_LOCK_DH 25
#define CRYPTO_LOCK_DSO 26 #define CRYPTO_LOCK_MALLOC2 26
#define CRYPTO_LOCK_DYNLOCK 27 #define CRYPTO_LOCK_DSO 27
#define CRYPTO_LOCK_ENGINE 28 #define CRYPTO_LOCK_DYNLOCK 28
#define CRYPTO_LOCK_UI 29 #define CRYPTO_LOCK_ENGINE 29
#define CRYPTO_NUM_LOCKS 30 #define CRYPTO_LOCK_UI 30
#define CRYPTO_NUM_LOCKS 31
#define CRYPTO_LOCK 1 #define CRYPTO_LOCK 1
#define CRYPTO_UNLOCK 2 #define CRYPTO_UNLOCK 2

View File

@ -144,6 +144,7 @@ static int initialized=0;
static unsigned int crypto_lock_rand = 0; /* may be set only when a thread static unsigned int crypto_lock_rand = 0; /* may be set only when a thread
* holds CRYPTO_LOCK_RAND * holds CRYPTO_LOCK_RAND
* (to prevent double locking) */ * (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 */ 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 */ /* 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); if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
st_idx=state_index; st_idx=state_index;
@ -361,7 +369,9 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
CRYPTO_w_lock(CRYPTO_LOCK_RAND); CRYPTO_w_lock(CRYPTO_LOCK_RAND);
/* prevent ssleay_rand_bytes() from trying to obtain the lock again */ /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
locking_thread = CRYPTO_thread_id(); locking_thread = CRYPTO_thread_id();
CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
crypto_lock_rand = 1; crypto_lock_rand = 1;
if (!initialized) if (!initialized)
@ -520,14 +530,23 @@ static int ssleay_rand_status(void)
/* check if we already have the lock /* check if we already have the lock
* (could happen if a RAND_poll() implementation calls RAND_status()) */ * (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) if (!do_not_lock)
{ {
CRYPTO_w_lock(CRYPTO_LOCK_RAND); CRYPTO_w_lock(CRYPTO_LOCK_RAND);
/* prevent ssleay_rand_bytes() from trying to obtain the lock again */ /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
locking_thread = CRYPTO_thread_id(); locking_thread = CRYPTO_thread_id();
CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
crypto_lock_rand = 1; crypto_lock_rand = 1;
} }