diff options
author | green <green@FreeBSD.org> | 2004-03-24 14:44:57 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 2004-03-24 14:44:57 +0000 |
commit | 4927c84b4815bd716a3ac5e194e98dbc7454f169 (patch) | |
tree | 13a024cec16b59e7ed4ef2c021be358c8b3fd0cd | |
parent | 6b2632b8257e8333c226e562eb4cb67d5b3584a2 (diff) | |
download | FreeBSD-src-4927c84b4815bd716a3ac5e194e98dbc7454f169.zip FreeBSD-src-4927c84b4815bd716a3ac5e194e98dbc7454f169.tar.gz |
Add locking so that arc4random(3) functions are all reentrant for
pthreads.
Submitted by: Christian S.J. Peron <maneo@bsdpro.com>
-rw-r--r-- | lib/libc/gen/arc4random.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/lib/libc/gen/arc4random.c b/lib/libc/gen/arc4random.c index 16dc80f..e2448d5 100644 --- a/lib/libc/gen/arc4random.c +++ b/lib/libc/gen/arc4random.c @@ -32,6 +32,9 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <fcntl.h> #include <unistd.h> +#include <pthread.h> + +#include "libc_private.h" #include "un-namespace.h" struct arc4_stream { @@ -40,10 +43,27 @@ struct arc4_stream { 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) @@ -89,11 +109,11 @@ arc4_stir(as) 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... */ @@ -140,14 +160,31 @@ arc4_getword(as) 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 @@ -155,18 +192,25 @@ arc4random_addrandom(dat, datlen) 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 |