[Midnightbsd-cvs] src [7490] trunk/lib/libc/stdlib: Replace access to /dev/ random with kernel pseudo random number source KERN_ARND and remove fallback.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Mar 20 18:18:46 EDT 2016


Revision: 7490
          http://svnweb.midnightbsd.org/src/?rev=7490
Author:   laffer1
Date:     2016-03-20 18:18:45 -0400 (Sun, 20 Mar 2016)
Log Message:
-----------
Replace access to /dev/random with kernel pseudo random number source KERN_ARND and remove fallback.

POSIX requires rand(3) return values in the 0 to rand max range, but ACM formula we have intranl state in the range 1, 0x7fffffffe  so our rand max value is never reached (zero as well)

Make this POSIX friendly.

Don't overflow on big seeds.

Obtained from: FreeBSD 9 stable.

Modified Paths:
--------------
    trunk/lib/libc/stdlib/rand.c
    trunk/lib/libc/stdlib/random.c

Modified: trunk/lib/libc/stdlib/rand.c
===================================================================
--- trunk/lib/libc/stdlib/rand.c	2016-03-20 21:57:32 UTC (rev 7489)
+++ trunk/lib/libc/stdlib/rand.c	2016-03-20 22:18:45 UTC (rev 7490)
@@ -36,11 +36,10 @@
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
-#include <sys/time.h>          /* for sranddev() */
+#include <sys/param.h>
+#include <sys/sysctl.h>
 #include <sys/types.h>
-#include <fcntl.h>             /* for sranddev() */
 #include <stdlib.h>
-#include <unistd.h>            /* for sranddev() */
 #include "un-namespace.h"
 
 #ifdef TEST
@@ -68,15 +67,15 @@
  */
 	long hi, lo, x;
 
-	/* Can't be initialized with 0, so use another value. */
-	if (*ctx == 0)
-		*ctx = 123459876;
+	/* Must be in [1, 0x7ffffffe] range at this point. */
 	hi = *ctx / 127773;
 	lo = *ctx % 127773;
 	x = 16807 * lo - 2836 * hi;
 	if (x < 0)
 		x += 0x7fffffff;
-	return ((*ctx = x) % ((u_long)RAND_MAX + 1));
+	*ctx = x;
+	/* Transform to [0, 0x7ffffffd] range. */
+	return (x - 1);
 #endif  /* !USE_WEAK_SEEDING */
 }
 
@@ -84,15 +83,32 @@
 int
 rand_r(unsigned int *ctx)
 {
-	u_long val = (u_long) *ctx;
-	int r = do_rand(&val);
+	u_long val;
+	int r;
 
-	*ctx = (unsigned int) val;
+#ifdef  USE_WEAK_SEEDING
+	val = *ctx;
+#else
+	/* Transform to [1, 0x7ffffffe] range. */
+	val = (*ctx % 0x7ffffffe) + 1;
+#endif
+	r = do_rand(&val);
+
+#ifdef  USE_WEAK_SEEDING
+	*ctx = (unsigned int)val;
+#else
+	*ctx = (unsigned int)(val - 1);
+#endif
 	return (r);
 }
 
 
-static u_long next = 1;
+static u_long next =
+#ifdef  USE_WEAK_SEEDING
+    1;
+#else
+    2;
+#endif
 
 int
 rand()
@@ -105,6 +121,10 @@
 u_int seed;
 {
 	next = seed;
+#ifndef USE_WEAK_SEEDING
+	/* Transform to [1, 0x7ffffffe] range. */
+	next = (next % 0x7ffffffe) + 1;
+#endif
 }
 
 
@@ -112,29 +132,24 @@
  * sranddev:
  *
  * Many programs choose the seed value in a totally predictable manner.
- * This often causes problems.  We seed the generator using the much more
- * secure random(4) interface.
+ * This often causes problems.  We seed the generator using pseudo-random
+ * data from the kernel.
  */
 void
 sranddev()
 {
-	int fd, done;
+	int mib[2];
+	size_t len;
 
-	done = 0;
-	fd = _open("/dev/random", O_RDONLY, 0);
-	if (fd >= 0) {
-		if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next))
-			done = 1;
-		_close(fd);
-	}
+	len = sizeof(next);
 
-	if (!done) {
-		struct timeval tv;
-		unsigned long junk;
-
-		gettimeofday(&tv, NULL);
-		srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
-	}
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_ARND;
+	sysctl(mib, 2, (void *)&next, &len, NULL, 0);
+#ifndef USE_WEAK_SEEDING
+	/* Transform to [1, 0x7ffffffe] range. */
+	next = (next % 0x7ffffffe) + 1;
+#endif
 }
 
 

Modified: trunk/lib/libc/stdlib/random.c
===================================================================
--- trunk/lib/libc/stdlib/random.c	2016-03-20 21:57:32 UTC (rev 7489)
+++ trunk/lib/libc/stdlib/random.c	2016-03-20 22:18:45 UTC (rev 7490)
@@ -34,12 +34,11 @@
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
-#include <sys/time.h>          /* for srandomdev() */
-#include <fcntl.h>             /* for srandomdev() */
+#include <sys/param.h>
+#include <sys/sysctl.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>            /* for srandomdev() */
 #include "un-namespace.h"
 
 /*
@@ -216,10 +215,8 @@
 static int rand_sep = SEP_3;
 static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
 
-static inline uint32_t good_rand(int32_t);
-
-static inline uint32_t good_rand (x)
-	int32_t x;
+static inline uint32_t
+good_rand(int32_t x)
 {
 #ifdef  USE_WEAK_SEEDING
 /*
@@ -264,8 +261,7 @@
  * for default usage relies on values produced by this routine.
  */
 void
-srandom(x)
-	unsigned long x;
+srandom(unsigned long x)
 {
 	int i, lim;
 
@@ -287,41 +283,29 @@
  * srandomdev:
  *
  * Many programs choose the seed value in a totally predictable manner.
- * This often causes problems.  We seed the generator using the much more
- * secure random(4) interface.  Note that this particular seeding
- * procedure can generate states which are impossible to reproduce by
- * calling srandom() with any value, since the succeeding terms in the
- * state buffer are no longer derived from the LC algorithm applied to
- * a fixed seed.
+ * This often causes problems.  We seed the generator using pseudo-random
+ * data from the kernel.
+ *
+ * Note that this particular seeding procedure can generate states
+ * which are impossible to reproduce by calling srandom() with any
+ * value, since the succeeding terms in the state buffer are no longer
+ * derived from the LC algorithm applied to a fixed seed.
  */
 void
-srandomdev()
+srandomdev(void)
 {
-	int fd, done;
+	int mib[2];
 	size_t len;
 
 	if (rand_type == TYPE_0)
-		len = sizeof state[0];
+		len = sizeof(state[0]);
 	else
-		len = rand_deg * sizeof state[0];
+		len = rand_deg * sizeof(state[0]);
 
-	done = 0;
-	fd = _open("/dev/random", O_RDONLY, 0);
-	if (fd >= 0) {
-		if (_read(fd, (void *) state, len) == (ssize_t) len)
-			done = 1;
-		_close(fd);
-	}
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_ARND;
+	sysctl(mib, 2, state, &len, NULL, 0);
 
-	if (!done) {
-		struct timeval tv;
-		unsigned long junk;
-
-		gettimeofday(&tv, NULL);
-		srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
-		return;
-	}
-
 	if (rand_type != TYPE_0) {
 		fptr = &state[rand_sep];
 		rptr = &state[0];
@@ -352,10 +336,7 @@
  * complain about mis-alignment, but you should disregard these messages.
  */
 char *
-initstate(seed, arg_state, n)
-	unsigned long seed;		/* seed for R.N.G. */
-	char *arg_state;		/* pointer to state array */
-	long n;				/* # bytes of state info */
+initstate(unsigned long seed, char *arg_state, long n)
 {
 	char *ostate = (char *)(&state[-1]);
 	uint32_t *int_arg_state = (uint32_t *)arg_state;
@@ -367,7 +348,7 @@
 	if (n < BREAK_0) {
 		(void)fprintf(stderr,
 		    "random: not enough state (%ld bytes); ignored.\n", n);
-		return(0);
+		return (0);
 	}
 	if (n < BREAK_1) {
 		rand_type = TYPE_0;
@@ -397,7 +378,7 @@
 		int_arg_state[0] = rand_type;
 	else
 		int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
-	return(ostate);
+	return (ostate);
 }
 
 /*
@@ -420,8 +401,7 @@
  * complain about mis-alignment, but you should disregard these messages.
  */
 char *
-setstate(arg_state)
-	char *arg_state;		/* pointer to state array */
+setstate(char *arg_state)
 {
 	uint32_t *new_state = (uint32_t *)arg_state;
 	uint32_t type = new_state[0] % MAX_TYPES;
@@ -452,7 +432,7 @@
 		fptr = &state[(rear + rand_sep) % rand_deg];
 	}
 	end_ptr = &state[rand_deg];		/* set end_ptr too */
-	return(ostate);
+	return (ostate);
 }
 
 /*
@@ -473,7 +453,7 @@
  * Returns a 31-bit random number.
  */
 long
-random()
+random(void)
 {
 	uint32_t i;
 	uint32_t *f, *r;
@@ -498,5 +478,5 @@
 
 		fptr = f; rptr = r;
 	}
-	return((long)i);
+	return ((long)i);
 }



More information about the Midnightbsd-cvs mailing list