summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2012-07-04 19:51:25 +0000
committerpjd <pjd@FreeBSD.org>2012-07-04 19:51:25 +0000
commit8cbf06904c76a2c9ed6b6e796cc669bb7b92e090 (patch)
treed0dad201d7d17d8750958079b6795c4eed40e39a
parent860961ab47e87d7fdd9b6940ef70346e37f33708 (diff)
downloadFreeBSD-src-8cbf06904c76a2c9ed6b6e796cc669bb7b92e090.zip
FreeBSD-src-8cbf06904c76a2c9ed6b6e796cc669bb7b92e090.tar.gz
Prefer sysctl to open/read/close for obtaining random data.
This method is more sandbox-friendly and also should be faster as only one syscall is needed instead of three. In case of an error fall back to the old method. Reviewed by: simon, gleb MFC after: 2 weeks
-rw-r--r--lib/libc/gen/arc4random.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/lib/libc/gen/arc4random.c b/lib/libc/gen/arc4random.c
index a2b235f..46059ab 100644
--- a/lib/libc/gen/arc4random.c
+++ b/lib/libc/gen/arc4random.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/sysctl.h>
#include <sys/time.h>
#include <pthread.h>
@@ -78,6 +79,9 @@ static struct arc4_stream rs;
static pid_t arc4_stir_pid;
static int arc4_count;
+extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
+ void *newp, size_t newlen);
+
static inline u_int8_t arc4_getbyte(void);
static void arc4_stir(void);
@@ -109,6 +113,28 @@ arc4_addrandom(u_char *dat, int datlen)
rs.j = rs.i;
}
+static size_t
+arc4_sysctl(u_char *buf, size_t size)
+{
+ int mib[2];
+ size_t len, done;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARND;
+ done = 0;
+
+ do {
+ len = size;
+ if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1)
+ return (done);
+ done += len;
+ buf += len;
+ size -= len;
+ } while (size > 0);
+
+ return (done);
+}
+
static void
arc4_stir(void)
{
@@ -123,12 +149,16 @@ arc4_stir(void)
arc4_init();
rs_initialized = 1;
}
- fd = _open(RANDOMDEV, O_RDONLY, 0);
done = 0;
- if (fd >= 0) {
- if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
- done = 1;
- (void)_close(fd);
+ if (arc4_sysctl((u_char *)&rdat, KEYSIZE) == KEYSIZE)
+ done = 1;
+ if (!done) {
+ fd = _open(RANDOMDEV, O_RDONLY, 0);
+ if (fd >= 0) {
+ if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
+ done = 1;
+ (void)_close(fd);
+ }
}
if (!done) {
(void)gettimeofday(&rdat.tv, NULL);
OpenPOWER on IntegriCloud