bin/63287: [patch] patch to make libc arc4random reentrant
Christian S.J. Peron
maneo at bsdpro.com
Mon Feb 23 13:50:11 PST 2004
>Number: 63287
>Category: bin
>Synopsis: [patch] patch to make libc arc4random reentrant
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Mon Feb 23 13:50:11 PST 2004
>Closed-Date:
>Last-Modified:
>Originator: Christian S.J. Peron
>Release: FreeBSD 5.2-CURRENT i386
>Organization:
>Environment:
System: FreeBSD movl 5.2-CURRENT FreeBSD 5.2-CURRENT #8: Mon Feb 2 22:04:49 GMT 2004 modulus at movl:/usr/src/sys/i386/compile/ROUTER i386
>Description:
Manipulation and permutation of S-boxes in the arc4random PRNG
is susceptible to data races during multithreaded operation.
I have enclosed a patch which serializes S-box manipulation.
>How-To-Repeat:
N/A
>Fix:
--- lib/libc/gen/arc4random.c.orig Mon Feb 23 20:15:57 2004
+++ lib/libc/gen/arc4random.c Mon Feb 23 21:05:12 2004
@@ -34,6 +34,9 @@
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
+#include <pthread.h>
+
+#include "libc_private.h"
#include "un-namespace.h"
struct arc4_stream {
@@ -42,10 +45,27 @@
u_int8_t s[256];
};
-static int rs_initialized;
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+#define RANDOMDEV "/dev/urandom"
+#define THREAD_LOCK() \
+ do { \
+ if (__isthreaded) \
+ _pthread_mutex_lock(&arc4random_mtx); \
+ } while (0)
+
+#define THREAD_UNLOCK() \
+ do { \
+ if (__isthreaded) \
+ _pthread_mutex_unlock(&arc4random_mtx); \
+ } while (0)
+
static struct arc4_stream rs;
+static int rs_initialized;
+static int rs_stired;
static inline u_int8_t arc4_getbyte(struct arc4_stream *);
+static void arc4_stir(struct arc4_stream *);
static inline void
arc4_init(as)
@@ -91,11 +111,11 @@
gettimeofday(&rdat.tv, NULL);
rdat.pid = getpid();
- fd = _open("/dev/urandom", O_RDONLY, 0);
+ fd = _open(RANDOMDEV, O_RDONLY, 0);
if (fd >= 0) {
(void) _read(fd, rdat.rnd, sizeof(rdat.rnd));
_close(fd);
- }
+ }
/* fd < 0? Ah, what the heck. We'll just take whatever was on the
* stack... */
@@ -142,14 +162,31 @@
return (val);
}
-void
-arc4random_stir()
+static void
+arc4_check_init(void)
{
if (!rs_initialized) {
arc4_init(&rs);
rs_initialized = 1;
}
+}
+
+static void
+arc4_check_stir(void)
+{
+ if (!rs_stired) {
+ arc4_stir(&rs);
+ rs_stired = 1;
+ }
+}
+
+void
+arc4random_stir()
+{
+ THREAD_LOCK();
+ arc4_check_init();
arc4_stir(&rs);
+ THREAD_UNLOCK();
}
void
@@ -157,18 +194,25 @@
u_char *dat;
int datlen;
{
- if (!rs_initialized)
- arc4random_stir();
+ THREAD_LOCK();
+ arc4_check_init();
+ arc4_check_stir();
arc4_addrandom(&rs, dat, datlen);
+ THREAD_UNLOCK();
}
u_int32_t
arc4random()
{
- if (!rs_initialized)
- arc4random_stir();
+ u_int32_t rnd;
+
+ THREAD_LOCK();
+ arc4_check_init();
+ arc4_check_stir();
+ rnd = arc4_getword(&rs);
+ THREAD_UNLOCK();
- return (arc4_getword(&rs));
+ return (rnd);
}
#if 0
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list