md_rand.c thread safety
authorBodo Möller <bodo@openssl.org>
Wed, 25 Jul 2001 17:18:02 +0000 (17:18 +0000)
committerBodo Möller <bodo@openssl.org>
Wed, 25 Jul 2001 17:18:02 +0000 (17:18 +0000)
CHANGES
crypto/cryptlib.c
crypto/crypto.h
crypto/rand/md_rand.c

diff --git a/CHANGES b/CHANGES
index 7ec2fc8fc39e51b5ed48749f2d21cde6b78b8878..0b42bed51c87d5da01657b024939fecc308d82ab 100644 (file)
--- a/CHANGES
+++ b/CHANGES
      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.
index fdb416d5981ed72d48e302055eca7ba0377fdc19..a98bf89e1b8a1ecb8390ff8ece59ff8de4d3b9cc 100644 (file)
@@ -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
        };
index 09ae4cb89d8fe67f1ae67b580d202e69110d9210..1fff49de9cbecda375089d9113e4d7c32bf6b2b2 100644 (file)
@@ -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
index 0db87d45100eedd984bae94cc900d0b5bbf25d4b..ed56536295d40fbc5248b74ec15a1d06b8a5ca7d 100644 (file)
@@ -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;
                }