Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Jul 2012 19:51:25 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r238118 - head/lib/libc/gen
Message-ID:  <201207041951.q64JpPXu029310@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pjd
Date: Wed Jul  4 19:51:25 2012
New Revision: 238118
URL: http://svn.freebsd.org/changeset/base/238118

Log:
  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

Modified:
  head/lib/libc/gen/arc4random.c

Modified: head/lib/libc/gen/arc4random.c
==============================================================================
--- head/lib/libc/gen/arc4random.c	Wed Jul  4 17:59:26 2012	(r238117)
+++ head/lib/libc/gen/arc4random.c	Wed Jul  4 19:51:25 2012	(r238118)
@@ -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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207041951.q64JpPXu029310>