On Wed, Sep 19, 2012 at 10:24 PM, Ted Unangst <t...@tedunangst.com> wrote:
> On Wed, Sep 19, 2012 at 18:50, Alexey Suslikov wrote:
>> On Wednesday, September 19, 2012, Theo de Raadt wrote:
>>
>>> > arc4random() is also thread-safe (it has interal locking) and very
>>> > desirable for other reasons. But no way to save state.
>>>
>>> The last part of this is intentional.  Saving the state of pseudo
>>> random number generators is a stupid concept from the 80's.
>>>
>>
>> I see many rng functions behaving very differently. Is it a good idea
>> to create a common locking layer on top of need-to-be-safe rng
>> functions? Or we should deal only with original problem (and only
>> port random.c code from netbsd)?
>
> just slap a mutex around it.

With the diff below Kannel no longer crashes. Only protecting random()
for now.

Make random() thread-safe by surrounding real call with a mutex locking.
Found by and diff from Roman Kravchuk. Mainly from NetBSD.

Index: include/thread_private.h
===================================================================
RCS file: /cvs/src/lib/libc/include/thread_private.h,v
retrieving revision 1.25
diff -u -p -r1.25 thread_private.h
--- include/thread_private.h    16 Oct 2011 06:29:56 -0000      1.25
+++ include/thread_private.h    20 Sep 2012 22:10:49 -0000
@@ -172,4 +172,16 @@ void       _thread_arc4_unlock(void);
                                                _thread_arc4_unlock();\
                                } while (0)

+void   _thread_random_lock(void);
+void   _thread_random_unlock(void);
+
+#define _RANDOM_LOCK()         do {                                    \
+                                       if (__isthreaded)               \
+                                               _thread_random_lock();  \
+                               } while (0)
+#define _RANDOM_UNLOCK()               do {                            \
+                                       if (__isthreaded)               \
+                                               _thread_random_unlock();\
+                               } while (0)
+
 #endif /* _THREAD_PRIVATE_H_ */
Index: stdlib/random.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/random.c,v
retrieving revision 1.17
diff -u -p -r1.17 random.c
--- stdlib/random.c     1 Jun 2012 01:01:57 -0000       1.17
+++ stdlib/random.c     20 Sep 2012 22:10:50 -0000
@@ -35,6 +35,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include "thread_private.h"

 /*
  * random.c:
@@ -376,21 +377,38 @@ setstate(char *arg_state)
  *
  * Returns a 31-bit random number.
  */
-long
-random(void)
+static long
+random_unlocked(void)
 {
        int32_t i;
+       int32_t *f, *r;

        if (rand_type == TYPE_0)
                i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
        else {
-               *fptr += *rptr;
-               i = (*fptr >> 1) & 0x7fffffff;  /* chucking least random bit */
-               if (++fptr >= end_ptr) {
-                       fptr = state;
-                       ++rptr;
-               } else if (++rptr >= end_ptr)
-                       rptr = state;
+               /*
+                * Use local variables rather than static variables for speed.
+                */
+               f = fptr; r = rptr;
+               *f += *r;
+               i = (*f >> 1) & 0x7fffffff;     /* chucking least random bit */
+               if (++f >= end_ptr) {
+                       f = state;
+                       ++r;
+               } else if (++r >= end_ptr)
+                       r = state;
+               fptr = f; rptr = r;
        }
        return((long)i);
+}
+
+long
+random(void)
+{
+       long r;
+
+       _RANDOM_LOCK();
+       r = random_unlocked();
+       _RANDOM_UNLOCK();
+       return (r);
 }
Index: thread/unithread_malloc_lock.c
===================================================================
RCS file: /cvs/src/lib/libc/thread/unithread_malloc_lock.c,v
retrieving revision 1.8
diff -u -p -r1.8 unithread_malloc_lock.c
--- thread/unithread_malloc_lock.c      13 Jun 2008 21:18:43 -0000      1.8
+++ thread/unithread_malloc_lock.c      20 Sep 2012 22:10:50 -0000
@@ -21,6 +21,12 @@ WEAK_PROTOTYPE(_thread_arc4_unlock);
 WEAK_ALIAS(_thread_arc4_lock);
 WEAK_ALIAS(_thread_arc4_unlock);

+WEAK_PROTOTYPE(_thread_random_lock);
+WEAK_PROTOTYPE(_thread_random_unlock);
+
+WEAK_ALIAS(_thread_random_lock);
+WEAK_ALIAS(_thread_random_unlock);
+
 void
 WEAK_NAME(_thread_malloc_lock)(void)
 {
@@ -53,6 +59,18 @@ WEAK_NAME(_thread_arc4_lock)(void)

 void
 WEAK_NAME(_thread_arc4_unlock)(void)
+{
+       return;
+}
+
+void
+WEAK_NAME(_thread_random_lock)(void)
+{
+       return;
+}
+
+void
+WEAK_NAME(_thread_random_unlock)(void)
 {
        return;
 }

Reply via email to