svn commit: r258288 - projects/random_number_generator/sys/dev/random

Mark Murray markm at FreeBSD.org
Sun Nov 17 23:43:52 UTC 2013


Author: markm
Date: Sun Nov 17 23:43:50 2013
New Revision: 258288
URL: http://svnweb.freebsd.org/changeset/base/258288

Log:
  Snapshot of WIP.
  
  Big refactor of the random_adaptors code to remove unnecessary layering.
  
  Also Yet Another Big Sweep Of Old code, essentially a rewrite of anything dodgy looking with my mind on efficiency. Some excess code is removed, and block copies are eliminated where possible.
  
  Locking is broken. This will be fixed in a follow-up.

Modified:
  projects/random_number_generator/sys/dev/random/dummy_rng.c
  projects/random_number_generator/sys/dev/random/ivy.c
  projects/random_number_generator/sys/dev/random/live_entropy_sources.c
  projects/random_number_generator/sys/dev/random/live_entropy_sources.h
  projects/random_number_generator/sys/dev/random/nehemiah.c
  projects/random_number_generator/sys/dev/random/random_adaptors.c
  projects/random_number_generator/sys/dev/random/random_adaptors.h
  projects/random_number_generator/sys/dev/random/random_harvestq.c
  projects/random_number_generator/sys/dev/random/random_harvestq.h
  projects/random_number_generator/sys/dev/random/randomdev.c
  projects/random_number_generator/sys/dev/random/randomdev.h
  projects/random_number_generator/sys/dev/random/randomdev_soft.c
  projects/random_number_generator/sys/dev/random/randomdev_soft.h
  projects/random_number_generator/sys/dev/random/yarrow.c
  projects/random_number_generator/sys/dev/random/yarrow.h

Modified: projects/random_number_generator/sys/dev/random/dummy_rng.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/dummy_rng.c	Sun Nov 17 23:28:10 2013	(r258287)
+++ projects/random_number_generator/sys/dev/random/dummy_rng.c	Sun Nov 17 23:43:50 2013	(r258288)
@@ -28,94 +28,66 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_random.h"
+
 #include <sys/param.h>
+#include <sys/conf.h>
 #include <sys/fcntl.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/mutex.h>
 #include <sys/random.h>
 #include <sys/syslog.h>
 #include <sys/systm.h>
-#include <sys/time.h>
 
 #include <dev/random/randomdev.h>
 #include <dev/random/random_adaptors.h>
 
-static struct mtx dummy_random_mtx;
-
-/* If no entropy device is loaded, don't spam the console with warnings */
-static int warned = 0;
-
-/* Used to fake out unused random calls in random_adaptor */
-static void
-random_null_func(void)
-{
-}
-
 static int
-dummy_random_poll(int events __unused, struct thread *td __unused)
+dummy_random_zero(void)
 {
 
 	return (0);
 }
 
-static int
-dummy_random_block(int flag)
-{
-	int error = 0;
-
-	mtx_lock(&dummy_random_mtx);
-
-	/* Blocking logic */
-	while (!error) {
-		if (flag & O_NONBLOCK)
-			error = EWOULDBLOCK;
-		else {
-			printf("random: dummy device blocking on read.\n");
-			error = msleep(&dummy_random_block,
-			    &dummy_random_mtx,
-			    PUSER | PCATCH, "block", 0);
-		}
-	}
-	mtx_unlock(&dummy_random_mtx);
-
-	return (error);
-}
-
 static void
-dummy_random_init(void)
+dummy_random(void)
 {
-
-	mtx_init(&dummy_random_mtx, "sleep mtx for dummy_random",
-	    NULL, MTX_DEF);
 }
 
+/* ARGSUSED */
 static void
-dummy_random_deinit(void)
+dummy_random_init(struct mtx *mtx __unused)
 {
 
-	mtx_destroy(&dummy_random_mtx);
+	randomdev_init_reader(dummy_random_read_phony);
 }
 
 /* This is used only by the internal read_random(9) call, and then only
  * if no entropy processor is loaded.
  *
- * DO NOT, REPEAT, DO NOT add this to the "struct random_adaptor" below!
- *
  * Make a token effort to provide _some_ kind of output. No warranty of
  * the quality of this output is made, mainly because its lousy.
  *
+ * This is only used by the internal read_random(9) call when no other
+ * adaptor is active.
+ *
+ * It has external scope due to the way things work in
+ * randomdev_[de]init_reader() that the rest of the world doesn't need to
+ * know about.
+ *
  * Caveat Emptor.
  */
-int
-dummy_random_read_phony(void *buf, int count)
+u_int
+dummy_random_read_phony(void *buf, u_int count)
 {
+	/* If no entropy device is loaded, don't spam the console with warnings */
+	static int warned = 0;
 	u_long randval;
 	int size, i;
 
 	if (!warned) {
-		log(LOG_WARNING, "random device not loaded; using insecure pseudo-random number generator\n");
+		log(LOG_WARNING, "random device not loaded/active; using insecure pseudo-random number generator\n");
 		warned = 1;
 	}
 
@@ -132,13 +104,12 @@ dummy_random_read_phony(void *buf, int c
 }
 
 struct random_adaptor randomdev_dummy = {
-	.ra_ident = "Dummy entropy device",
-	.ra_init = dummy_random_init,
-	.ra_deinit = dummy_random_deinit,
-	.ra_block = dummy_random_block,
-	.ra_poll = dummy_random_poll,
-	.ra_read = (random_adaptor_read_func_t *)random_null_func,
-	.ra_reseed = (random_adaptor_reseed_func_t *)random_null_func,
-	.ra_seeded = 0, /* This device can never be seeded */
+	.ra_ident = "Dummy",
 	.ra_priority = 1, /* Bottom priority, so goes to last position */
+	.ra_reseed = dummy_random,
+	.ra_seeded = (random_adaptor_seeded_func_t *)dummy_random_zero,
+	.ra_read = (random_adaptor_read_func_t *)dummy_random_zero,
+	.ra_write = (random_adaptor_write_func_t *)dummy_random_zero,
+	.ra_init = dummy_random_init,
+	.ra_deinit = dummy_random,
 };

Modified: projects/random_number_generator/sys/dev/random/ivy.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/ivy.c	Sun Nov 17 23:28:10 2013	(r258287)
+++ projects/random_number_generator/sys/dev/random/ivy.c	Sun Nov 17 23:43:50 2013	(r258288)
@@ -52,10 +52,10 @@ __FBSDID("$FreeBSD$");
 
 #define	RETRY_COUNT	10
 
-static int random_ivy_read(void *, int);
+static u_int random_ivy_read(void *, u_int);
 
 static struct live_entropy_source random_ivy = {
-	.les_ident = "Hardware, Intel IvyBridge+ RNG",
+	.les_ident = "Intel IvyBridge+ RNG",
 	.les_source = RANDOM_PURE_RDRAND,
 	.les_read = random_ivy_read
 };
@@ -85,15 +85,17 @@ ivy_rng_store(long *buf)
 #endif
 }
 
-static int
-random_ivy_read(void *buf, int c)
+/* It is specifically allowed that buf is a multiple of sizeof(long) */
+static u_int
+random_ivy_read(void *buf, u_int c)
 {
 	long *b;
-	int count;
+	u_int count;
 
 	KASSERT(c % sizeof(long) == 0, ("partial read %d", c));
-	for (b = buf, count = c; count > 0; count -= sizeof(long), b++) {
-		if (ivy_rng_store(b) == 0)
+	b = buf;
+	for (count = c; count > 0; count -= sizeof(long)) {
+		if (ivy_rng_store(b++) == 0)
 			break;
 	}
 	return (c - count);

Modified: projects/random_number_generator/sys/dev/random/live_entropy_sources.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/live_entropy_sources.c	Sun Nov 17 23:28:10 2013	(r258287)
+++ projects/random_number_generator/sys/dev/random/live_entropy_sources.c	Sun Nov 17 23:43:50 2013	(r258288)
@@ -28,6 +28,8 @@
 #include <sys/param.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_random.h"
+
 #include <sys/kernel.h>
 #include <sys/libkern.h>
 #include <sys/lock.h>
@@ -52,7 +54,7 @@ __FBSDID("$FreeBSD$");
 /*
  * The les_lock protects the consistency of the "struct les_head les_sources"
  */
-static struct sx les_lock; /* need a sleepable lock */
+static struct sx les_lock; /* Need a sleepable lock for the sbuf/sysctl stuff. */
 
 LIST_HEAD(les_head, live_entropy_sources);
 static struct les_head les_sources = LIST_HEAD_INITIALIZER(les_sources);
@@ -124,7 +126,6 @@ live_entropy_source_handler(SYSCTL_HANDL
  *
  * BEWARE!!!
  * This function runs inside the RNG thread! Don't do anything silly!
- * Remember that we are NOT holding harvest_mtx on entry!
  */
 /* XXXRW: get_cyclecount() is cheap on most modern hardware, where cycle
  * counters are built in, but on older hardware it will do a real time clock
@@ -135,7 +136,8 @@ live_entropy_sources_feed(void)
 {
 	static struct harvest_event event;
 	struct live_entropy_sources *lles;
-	int i, n, read_rate;
+	int i, read_rate;
+	u_int n;
 
 	sx_slock(&les_lock);
 
@@ -156,7 +158,7 @@ live_entropy_sources_feed(void)
 			/* This *must* be quick, since it's a live entropy source. */
 			n = lles->lles_rsource->les_read(event.he_entropy, HARVESTSIZE);
 			KASSERT((n > 0 && n <= HARVESTSIZE), ("very bad return from les_read (= %d) in %s", n, __func__));
-			memset(event.he_entropy + n, 0, HARVESTSIZE - (u_int)n);
+			memset(event.he_entropy + n, 0, HARVESTSIZE - n);
 
 			/* Do the actual entropy insertion */
 			harvest_process_event(&event);

Modified: projects/random_number_generator/sys/dev/random/live_entropy_sources.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/live_entropy_sources.h	Sun Nov 17 23:28:10 2013	(r258287)
+++ projects/random_number_generator/sys/dev/random/live_entropy_sources.h	Sun Nov 17 23:43:50 2013	(r258288)
@@ -30,6 +30,8 @@
 #ifndef SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
 #define SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED
 
+typedef u_int random_live_read_func_t(void *, u_int);
+
 /*
  * Live entropy source is a source of entropy that can provide
  * specified or approximate amount of entropy immediately upon request or within
@@ -38,7 +40,7 @@
 struct live_entropy_source {
 	const char			*les_ident;
 	enum random_entropy_source	 les_source;
-	random_adaptor_read_func_t	*les_read;
+	random_live_read_func_t		*les_read;
 };
 
 struct live_entropy_sources {

Modified: projects/random_number_generator/sys/dev/random/nehemiah.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/nehemiah.c	Sun Nov 17 23:28:10 2013	(r258287)
+++ projects/random_number_generator/sys/dev/random/nehemiah.c	Sun Nov 17 23:43:50 2013	(r258288)
@@ -50,10 +50,10 @@ __FBSDID("$FreeBSD$");
 
 static void random_nehemiah_init(void);
 static void random_nehemiah_deinit(void);
-static int random_nehemiah_read(void *, int);
+static u_int random_nehemiah_read(void *, u_int);
 
 static struct live_entropy_source random_nehemiah = {
-	.les_ident = "Hardware, VIA Nehemiah Padlock RNG",
+	.les_ident = "VIA Nehemiah Padlock RNG",
 	.les_source = RANDOM_PURE_NEHEMIAH,
 	.les_read = random_nehemiah_read
 };
@@ -100,8 +100,9 @@ random_nehemiah_deinit(void)
 	fpu_kern_free_ctx(fpu_ctx_save);
 }
 
-static int
-random_nehemiah_read(void *buf, int c)
+/* It is specifically allowed that buf is a multiple of sizeof(long) */
+static u_int
+random_nehemiah_read(void *buf, u_int c)
 {
 	uint8_t *b;
 	size_t count, ret;

Modified: projects/random_number_generator/sys/dev/random/random_adaptors.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.c	Sun Nov 17 23:28:10 2013	(r258287)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.c	Sun Nov 17 23:43:50 2013	(r258288)
@@ -29,7 +29,11 @@
 #include <sys/param.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_random.h"
+
 #include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
 #include <sys/kernel.h>
 #include <sys/kthread.h>
 #include <sys/libkern.h>
@@ -40,6 +44,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/queue.h>
 #include <sys/random.h>
 #include <sys/sbuf.h>
+#include <sys/selinfo.h>
 #include <sys/sx.h>
 #include <sys/sysctl.h>
 #include <sys/uio.h>
@@ -48,25 +53,105 @@ __FBSDID("$FreeBSD$");
 #include <dev/random/randomdev.h>
 #include <dev/random/random_adaptors.h>
 
-/* These are the data structures and associated items that need to be locked against
- * "under-the-feet" changes.
+/* The random_adaptors_lock protects random_adaptors_list and friends and random_adaptor.
+ * We need a sleepable lock for uiomove/block/poll/sbuf/sysctl.
  */
-static struct sx random_adaptors_lock; /* need a sleepable lock */
-
+static struct sx random_adaptors_lock;
 LIST_HEAD(adaptors_head, random_adaptors);
 static struct adaptors_head random_adaptors_list = LIST_HEAD_INITIALIZER(random_adaptors_list);
 static struct random_adaptor *random_adaptor = NULL; /* Currently active adaptor */
-/* End of data items requiring adaptor lock protection */
+/* End of data items requiring random_adaptors_lock protection */
 
-/* The rate mutex protects the consistency of the read-rate logic. */
-struct mtx rate_mtx;
+/* The random_rate_mtx mutex protects the consistency of the read-rate logic. */
+struct mtx random_rate_mtx;
 int random_adaptor_read_rate_cache;
-/* End of data items requiring rate mutex protection */
+/* End of data items requiring random_rate_mtx mutex protection */
+
+/* The random_reseed_mtx mutex protects seeding and polling/blocking.
+ * This is passed into the software entropy hasher/processor.
+ */
+struct mtx random_reseed_mtx;
+/* End of data items requiring random_reseed_mtx mutex protection */
 
-MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
+static struct selinfo rsel;
+
+/* Utility routine to change active adaptor when the random_adaptors_list
+ * gets modified.
+ *
+ * Walk a list of registered random(4) adaptors and pick either a requested
+ * one or the highest priority one, whichever comes first. Panic on failure
+ * as the fallback must always be the "dummy" adaptor.
+ */
+static void
+random_adaptor_choose(void)
+{
+	char			 rngs[128], *token, *cp;
+	struct random_adaptors	*rra, *rrai;
+	struct random_adaptor	*random_adaptor_previous;
+	int			 primax;
+
+	/* We are going to be messing with random_adaptor.
+	 * Exclusive lock is mandatory.
+	 */
+	sx_assert(&random_adaptors_lock, SA_XLOCKED);
+
+	random_adaptor_previous = random_adaptor;
+
+	random_adaptor = NULL;
+	if (TUNABLE_STR_FETCH("kern.random.active_adaptor", rngs, sizeof(rngs))) {
+		cp = rngs;
 
-static void random_adaptor_choose(void);
+		while ((token = strsep(&cp, ",")) != NULL) {
+			LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
+				if (strcmp(rra->rra_name, token) == 0) {
+					random_adaptor = rra->rra_ra;
+					break;
+				}
+			if (random_adaptor != NULL) {
+				printf("random: selecting requested adaptor <%s>\n",
+				    random_adaptor->ra_ident);
+				break;
+			}
+			else
+				printf("random: requested adaptor <%s> not available\n",
+				    token);
+		}
+	}
 
+	primax = 0;
+	if (random_adaptor == NULL) {
+		/*
+		 * Fall back to the highest priority item on the available
+		 * RNG list.
+		 */
+		LIST_FOREACH(rrai, &random_adaptors_list, rra_entries) {
+			if (rrai->rra_ra->ra_priority >= primax) {
+				random_adaptor = rrai->rra_ra;
+				primax = rrai->rra_ra->ra_priority;
+			}
+		}
+		if (random_adaptor != NULL)
+			printf("random: selecting highest priority adaptor <%s>\n",
+			    random_adaptor->ra_ident);
+	}
+
+	KASSERT(random_adaptor != NULL, ("adaptor not found"));
+
+	/* If we are changing adaptors, deinit the old and init the new. */
+	if (random_adaptor != random_adaptor_previous) {
+#ifdef RANDOM_DEBUG
+		printf("random: %s - changing from %s to %s\n", __func__,
+		    (random_adaptor_previous == NULL ? "NULL" : random_adaptor_previous->ra_ident),
+		    random_adaptor->ra_ident);
+#endif
+		if (random_adaptor_previous != NULL)
+			(random_adaptor_previous->ra_deinit)();
+		(random_adaptor->ra_init)(&random_reseed_mtx);
+	}
+}
+
+
+/* XXX: FIX!! Make sure we are not inserting a duplicate */
 void
 random_adaptor_register(const char *name, struct random_adaptor *ra)
 {
@@ -79,12 +164,8 @@ random_adaptor_register(const char *name
 	rra->rra_ra = ra;
 
 	sx_xlock(&random_adaptors_lock);
-
-	/* XXX: FIX!! Make sure we are not inserting a duplicate */
 	LIST_INSERT_HEAD(&random_adaptors_list, rra, rra_entries);
-
 	random_adaptor_choose();
-
 	sx_xunlock(&random_adaptors_lock);
 
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
@@ -99,80 +180,133 @@ random_adaptor_deregister(const char *na
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
 	sx_xlock(&random_adaptors_lock);
-
 	LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
 		if (strcmp(rra->rra_name, name) == 0) {
 			LIST_REMOVE(rra, rra_entries);
 			break;
 		}
-
 	random_adaptor_choose();
-	/* It is conceivable that there is no active random adaptor here,
-	 * e.g. at shutdown.
-	 */
-
 	sx_xunlock(&random_adaptors_lock);
 
-	if (rra != NULL)
-		free(rra, M_ENTROPY);
+	free(rra, M_ENTROPY);
 }
 
+/*
+ * Per-instance structure.
+ *
+ * List of locks
+ * XXX: FIX!!
+ */
+struct random_adaptor_softc {
+	int oink;
+	int tweet;
+};
+
+static void
+random_adaptor_dtor(void *data)
+{
+	struct random_adaptor_softc *ras = data;
+
+	free(ras, M_ENTROPY);
+}
+
+/* ARGSUSED */
 int
-random_adaptor_block(int flag)
+random_adaptor_open(struct cdev *dev __unused, int flags, int mode __unused, struct thread *td __unused)
 {
-	int ret;
+	struct random_adaptor_softc *ras;
 
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
-	sx_slock(&random_adaptors_lock);
+	ras = malloc(sizeof(struct random_adaptor_softc), M_ENTROPY, M_WAITOK|M_ZERO);
+	/* XXX: FIX!! Set up softc here */
 
-	ret = random_adaptor->ra_block(flag);
+	devfs_set_cdevpriv(ras, random_adaptor_dtor);
 
-	sx_sunlock(&random_adaptors_lock);
+	/* Give the source a chance to do some pre-read/write startup */
+	if (flags & FREAD) {
+		sx_slock(&random_adaptors_lock);
+		(random_adaptor->ra_read)(NULL, 0);
+		sx_sunlock(&random_adaptors_lock);
+	} else if (flags & FWRITE) {
+		sx_slock(&random_adaptors_lock);
+		(random_adaptor->ra_write)(NULL, 0);
+		sx_sunlock(&random_adaptors_lock);
+	}
+
+	return (0);
+}
 
-	return ret;
+/* ARGSUSED */
+int
+random_adaptor_close(struct cdev *dev __unused, int flags, int fmt __unused, struct thread *td __unused)
+{
+
+	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+
+	/* Give the source a chance to do some post-read/write shutdown */
+	if (flags & FREAD) {
+		sx_slock(&random_adaptors_lock);
+		(random_adaptor->ra_read)(NULL, 1);
+		sx_sunlock(&random_adaptors_lock);
+	} else if (flags & FWRITE) {
+		sx_slock(&random_adaptors_lock);
+		(random_adaptor->ra_write)(NULL, 1);
+		sx_sunlock(&random_adaptors_lock);
+	}
+
+	return (0);
 }
 
+/* ARGSUSED */
 int
-random_adaptor_read(struct uio *uio, int flag)
+random_adaptor_read(struct cdev *dev __unused, struct uio *uio, int flags __unused)
 {
-	int c, error = 0;
 	void *random_buf;
+	int c, error;
+	u_int npages;
+	struct random_adaptor_softc *ras;
 
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
-	/* The read-rate stuff is a *VERY* crude measure of the instantaneous read rate, designed
-	 * to increase the use of 'live' entropy sources when lots of reads are done.
-	 */
-	mtx_lock(&rate_mtx);
-	random_adaptor_read_rate_cache += (int)((uio->uio_resid + PAGE_SIZE + 1)/PAGE_SIZE);
-	mtx_unlock(&rate_mtx);
+	error = devfs_get_cdevpriv((void **)&ras);
+	if (error == 0) {
 
-	sx_slock(&random_adaptors_lock);
+		sx_slock(&random_adaptors_lock);
 
-	/* Blocking logic */
-	if (random_adaptor->ra_seeded)
-		error = (random_adaptor->ra_block)(flag);
-
-	/* The actual read */
-	if (!error) {
-
-		random_buf = (void *)malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK);
-
-		while (uio->uio_resid > 0 && !error) {
-			c = MIN(uio->uio_resid, PAGE_SIZE);
-			c = (random_adaptor->ra_read)(random_buf, c);
-			error = uiomove(random_buf, c, uio);
+		/* Blocking logic */
+		mtx_lock(&random_reseed_mtx);
+		while (!random_adaptor->ra_seeded() && !error) {
+			if (flags & O_NONBLOCK)
+				error = EWOULDBLOCK;
+			else
+				error = msleep(&random_adaptor, &random_reseed_mtx, PUSER | PCATCH, "block", 0);
 		}
-		/* Finished reading; let the source know so it can do some
-		 * optional housekeeping */
-		(random_adaptor->ra_read)(NULL, 0);
+		mtx_unlock(&random_reseed_mtx);
 
-		free(random_buf, M_ENTROPY);
+		/* The actual read */
+		if (!error) {
+			/* The read-rate stuff is a *VERY* crude indication of the instantaneous read rate,
+			 * designed to increase the use of 'live' entropy sources when lots of reads are done.
+			 */
+			mtx_lock(&random_rate_mtx);
+			npages = (uio->uio_resid + PAGE_SIZE - 1)/PAGE_SIZE;
+			random_adaptor_read_rate_cache += npages;
+			random_adaptor_read_rate_cache = MIN(random_adaptor_read_rate_cache, 32);
+			mtx_unlock(&random_rate_mtx);
+
+			random_buf = (void *)malloc(npages*PAGE_SIZE, M_ENTROPY, M_WAITOK);
+			while (uio->uio_resid > 0 && !error) {
+				c = MIN(uio->uio_resid, npages*PAGE_SIZE);
+				(random_adaptor->ra_read)(random_buf, c);
+				error = uiomove(random_buf, c, uio);
+			}
+			free(random_buf, M_ENTROPY);
+		}
 
-	}
+		sx_sunlock(&random_adaptors_lock);
 
-	sx_sunlock(&random_adaptors_lock);
+	}
 
 	return (error);
 }
@@ -182,98 +316,83 @@ random_adaptor_read_rate(void)
 {
 	int ret;
 
-	mtx_lock(&rate_mtx);
-	ret = random_adaptor_read_rate_cache = random_adaptor_read_rate_cache ? random_adaptor_read_rate_cache%32 + 1 : 1;
-	mtx_unlock(&rate_mtx);
+	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
+
+	mtx_lock(&random_rate_mtx);
+	ret = random_adaptor_read_rate_cache;
+	mtx_unlock(&random_rate_mtx);
 
 	return (ret);
 }
 
+/* ARGSUSED */
 int
-random_adaptor_poll(int events, struct thread *td)
+random_adaptor_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
 {
-	int revents = 0;
+	int error;
+	struct random_adaptor_softc *ras;
 
-	sx_slock(&random_adaptors_lock);
+	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
-	if (events & (POLLIN | POLLRDNORM)) {
-		if (random_adaptor->ra_seeded)
-			revents = events & (POLLIN | POLLRDNORM);
-		else
-			revents = (random_adaptor->ra_poll)(events, td);
+	sx_slock(&random_adaptors_lock);
+	error = devfs_get_cdevpriv((void **)&ras);
+	if (error == 0) {
+		/* We used to allow this to insert userland entropy.
+		 * We don't any more because (1) this so-called entropy
+		 * is usually lousy and (b) its vaguely possible to
+		 * mess with entropy harvesting by overdoing a write.
+		 * Now we just ignore input like /dev/null does.
+		 */
+		/* XXX: FIX!! Now that RWFILE is gone, we need to get this back.
+		 * ALSO: See devfs_get_cdevpriv(9) and friends for ways to build per-session nodes.
+		 */
+		uio->uio_resid = 0;
+		/* c = (random_adaptor->ra_write)(random_buf, c); */
 	}
-
 	sx_sunlock(&random_adaptors_lock);
 
-	return (revents);
+	return (error);
 }
 
-/*
- * Walk a list of registered random(4) adaptors and pick either a requested
- * one or the highest priority one, whichever comes first. Panic on failure
- * as the fallback must be the "dummy" adaptor.
- */
-static void
-random_adaptor_choose(void)
+/* ARGSUSED */
+int
+random_adaptor_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
 {
-	char			 rngs[128], *token, *cp;
-	struct random_adaptors	*rra, *rrai;
-	struct random_adaptor	*random_adaptor_previous;
-	int			 primax;
-
-	/* We are going to be messing with random_adaptor.
-	 * Exclusive lock is mandatory.
-	 */
-	sx_assert(&random_adaptors_lock, SA_XLOCKED);
+	struct random_adaptor_softc *ras;
 
-	random_adaptor_previous = random_adaptor;
+	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
-	random_adaptor = NULL;
-	if (TUNABLE_STR_FETCH("kern.random.active_adaptor", rngs, sizeof(rngs))) {
-		cp = rngs;
+	if (devfs_get_cdevpriv((void **)&ras) != 0)
+		return (events &
+		    (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
 
-		while ((token = strsep(&cp, ",")) != NULL) {
-			LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
-				if (strcmp(rra->rra_name, token) == 0) {
-					random_adaptor = rra->rra_ra;
-					break;
-				}
-			if (random_adaptor != NULL) {
-				printf("random: selecting requested adaptor <%s>\n",
-				    random_adaptor->ra_ident);
-				break;
-			}
-			else
-				printf("random: requested adaptor <%s> not available\n",
-				    token);
-		}
+	sx_slock(&random_adaptors_lock);
+	mtx_lock(&random_reseed_mtx);
+	if (events & (POLLIN | POLLRDNORM)) {
+		if (random_adaptor->ra_seeded())
+			events &= (POLLIN | POLLRDNORM);
+		else
+			selrecord(td, &rsel);
 	}
+	mtx_unlock(&random_reseed_mtx);
+	sx_sunlock(&random_adaptors_lock);
 
-	primax = 0;
-	if (random_adaptor == NULL) {
-		/*
-		 * Fall back to the highest priority item on the available
-		 * RNG list.
-		 */
-		LIST_FOREACH(rrai, &random_adaptors_list, rra_entries) {
-			if (rrai->rra_ra->ra_priority >= primax) {
-				random_adaptor = rrai->rra_ra;
-				primax = rrai->rra_ra->ra_priority;
-			}
-		}
-		if (random_adaptor != NULL)
-			printf("random: selecting highest priority adaptor <%s>\n",
-			    random_adaptor->ra_ident);
-	}
+	return (events);
+}
 
-	KASSERT(random_adaptor != NULL, ("adaptor not found"));
+/* This will be called by the entropy processor when it seeds itself and becomes secure */
+void
+random_adaptor_unblock(void)
+{
 
-	/* If we are changing adaptors, deinit the old and init the new. */
-	if (random_adaptor != random_adaptor_previous) {
-		if (random_adaptor_previous != NULL)
-			(random_adaptor_previous->ra_deinit)();
-		(random_adaptor->ra_init)();
-	}
+	mtx_assert(&random_reseed_mtx, MA_OWNED);
+
+	selwakeuppri(&rsel, PUSER);
+	wakeup(&random_adaptor);
+	printf("random: unblocking device.\n");
+
+	/* Do arc4random(9) a favour while we are about it. */
+	(void)atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_NONE, ARC4_ENTR_HAVE);
 }
 
 static int
@@ -284,9 +403,7 @@ random_sysctl_adaptors_handler(SYSCTL_HA
 	int error, count;
 
 	sx_slock(&random_adaptors_lock);
-
 	sbuf_new_for_sysctl(&sbuf, NULL, 64, req);
-
 	count = 0;
 	LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
 		sbuf_printf(&sbuf, "%s%s(%d)",
@@ -294,7 +411,6 @@ random_sysctl_adaptors_handler(SYSCTL_HA
 
 	error = sbuf_finish(&sbuf);
 	sbuf_delete(&sbuf);
-
 	sx_sunlock(&random_adaptors_lock);
 
 	return (error);
@@ -310,19 +426,14 @@ random_sysctl_active_adaptor_handler(SYS
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
 	sx_slock(&random_adaptors_lock);
-
 	sbuf_new_for_sysctl(&sbuf, NULL, 16, req);
-
 	LIST_FOREACH(rra, &random_adaptors_list, rra_entries)
 		if (rra->rra_ra == random_adaptor) {
 			sbuf_cat(&sbuf, rra->rra_name);
 			break;
 		}
-
-
 	error = sbuf_finish(&sbuf);
 	sbuf_delete(&sbuf);
-
 	sx_sunlock(&random_adaptors_lock);
 
 	return (error);
@@ -344,30 +455,37 @@ random_adaptors_init(void *unused __unus
 	    "Active Random Number Generator Adaptor");
 
 	sx_init(&random_adaptors_lock, "random_adaptors");
-	mtx_init(&rate_mtx, "read rate mutex", NULL, MTX_DEF);
 
-	/* This dummy "thing" is not a module by itself, but part of the
+	mtx_init(&random_rate_mtx, "read rate mutex", NULL, MTX_DEF);
+	mtx_init(&random_reseed_mtx, "read rate mutex", NULL, MTX_DEF);
+
+	/* The dummy adaptor is not a module by itself, but part of the
 	 * randomdev module.
 	 */
 	random_adaptor_register("dummy", &randomdev_dummy);
 }
+SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+    random_adaptors_init, NULL);
 
 /* ARGSUSED */
 static void
 random_adaptors_deinit(void *unused __unused)
 {
-	/* Don't do this! Panic will follow. */
+	/* Don't do this! Panic will surely follow! */
 	/* random_adaptor_deregister("dummy"); */
 
-	mtx_destroy(&rate_mtx);
+	mtx_destroy(&random_reseed_mtx);
+	mtx_destroy(&random_rate_mtx);
+
 	sx_destroy(&random_adaptors_lock);
 }
+SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST,
+    random_adaptors_deinit, NULL);
 
 /*
  * First seed.
  *
  * NB! NB! NB!
- *
  * NB! NB! NB!
  *
  * It turns out this is bloody dangerous. I was fiddling with code elsewhere
@@ -376,6 +494,9 @@ random_adaptors_deinit(void *unused __un
  * As crap randomness is not directly distinguishable from good randomness, this
  * could have gone unnoticed for quite a while.
  *
+ * NB! NB! NB!
+ * NB! NB! NB!
+ *
  * Very luckily, the probe-time entropy is very nearly good enough to cause a
  * first seed all of the time, and the default settings for other entropy
  * harvesting causes a proper, safe, first seed (unblock) in short order after that.
@@ -394,9 +515,7 @@ random_adaptors_seed(void *unused __unus
 	KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__));
 
 	sx_slock(&random_adaptors_lock);
-
 	random_adaptor->ra_reseed();
-
 	sx_sunlock(&random_adaptors_lock);
 
 	arc4rand(NULL, 0, 1);
@@ -404,8 +523,3 @@ random_adaptors_seed(void *unused __unus
 SYSINIT(random_seed, SI_SUB_INTRINSIC_POST, SI_ORDER_LAST,
     random_adaptors_reseed, NULL);
 #endif /*  RANDOM_AUTOSEED */
-
-SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_SECOND,
-    random_adaptors_init, NULL);
-SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_SECOND,
-    random_adaptors_deinit, NULL);

Modified: projects/random_number_generator/sys/dev/random/random_adaptors.h
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_adaptors.h	Sun Nov 17 23:28:10 2013	(r258287)
+++ projects/random_number_generator/sys/dev/random/random_adaptors.h	Sun Nov 17 23:43:50 2013	(r258288)
@@ -31,25 +31,22 @@
 
 MALLOC_DECLARE(M_ENTROPY);
 
-typedef void random_adaptor_init_func_t(void);
+typedef void random_adaptor_init_func_t(struct mtx *);
 typedef void random_adaptor_deinit_func_t(void);
-
-typedef int random_adaptor_block_func_t(int);
-typedef int random_adaptor_read_func_t(void *, int);
-typedef int random_adaptor_poll_func_t(int, struct thread *);
-
+typedef void random_adaptor_read_func_t(uint8_t *, u_int);
+typedef void random_adaptor_write_func_t(uint8_t *, u_int);
+typedef int random_adaptor_seeded_func_t(void);
 typedef void random_adaptor_reseed_func_t(void);
 
 struct random_adaptor {
 	const char			*ra_ident;
-	int				ra_seeded;
-	int				ra_priority;
+	int				 ra_priority;
 	random_adaptor_init_func_t	*ra_init;
 	random_adaptor_deinit_func_t	*ra_deinit;
-	random_adaptor_block_func_t	*ra_block;
 	random_adaptor_read_func_t	*ra_read;
-	random_adaptor_poll_func_t	*ra_poll;
+	random_adaptor_write_func_t	*ra_write;
 	random_adaptor_reseed_func_t	*ra_reseed;
+	random_adaptor_seeded_func_t	*ra_seeded;
 };
 
 struct random_adaptors {
@@ -64,10 +61,13 @@ extern struct random_adaptor randomdev_d
 void random_adaptor_register(const char *, struct random_adaptor *);
 void random_adaptor_deregister(const char *);
 
-int random_adaptor_block(int);
-int random_adaptor_read(struct uio *, int);
-int random_adaptor_poll(int, struct thread *);
+int random_adaptor_open(struct cdev *, int, int, struct thread *);
+int random_adaptor_read(struct cdev *, struct uio *, int);
+int random_adaptor_write(struct cdev *, struct uio *, int);
+int random_adaptor_close(struct cdev *, int, int, struct thread *);
+int random_adaptor_poll(struct cdev *, int, struct thread *);
 
 int random_adaptor_read_rate(void);
+void random_adaptor_unblock(void);
 
 #endif /* SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED */

Modified: projects/random_number_generator/sys/dev/random/random_harvestq.c
==============================================================================
--- projects/random_number_generator/sys/dev/random/random_harvestq.c	Sun Nov 17 23:28:10 2013	(r258287)
+++ projects/random_number_generator/sys/dev/random/random_harvestq.c	Sun Nov 17 23:43:50 2013	(r258288)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/random.h>
+#include <sys/sbuf.h>
 #include <sys/sysctl.h>
 #include <sys/unistd.h>
 
@@ -52,6 +53,9 @@ __FBSDID("$FreeBSD$");
 #include <dev/random/random_harvestq.h>
 #include <dev/random/live_entropy_sources.h>
 
+/* List for the dynamic sysctls */
+static struct sysctl_ctx_list random_clist;
+
 /*
  * How many events to queue up. We create this many items in
  * an 'empty' queue, then transfer them to the 'harvest' queue with
@@ -64,7 +68,7 @@ __FBSDID("$FreeBSD$");
  * The harvest mutex protects the consistency of the entropy Fifos and
  * empty fifo and other associated structures.
  */
-struct mtx	harvest_mtx;
+static struct mtx harvest_mtx;
 
 /* Lockable FIFO queue holding entropy buffers */
 struct entropyfifo {
@@ -83,6 +87,11 @@ u_int harvest_destination[ENTROPYSOURCE]
 /* Function called to process one harvested stochastic event */
 void (*harvest_process_event)(struct harvest_event *);
 
+/* Allow the sysadmin to select the broad category of
+ * entropy types to harvest.
+ */
+static u_int harvest_source_mask = ((1<<RANDOM_ENVIRONMENTAL_END) - 1);
+
 /* Pool count is used by anything needing to know how many entropy
  * pools are currently being maintained.
  * This is of use to (e.g.) the live source feed where we need to give
@@ -91,7 +100,7 @@ void (*harvest_process_event)(struct har
 int harvest_pool_count;
 
 /* <0 to end the kthread, 0 to let it run, 1 to flush the harvest queues */
-int random_kthread_control = 0;
+static int random_kthread_control = 0;
 
 static struct proc *random_kthread_proc;
 
@@ -153,12 +162,75 @@ random_kthread(void *arg __unused)
 }
 
 void
+random_harvestq_flush(void)
+{
+
+	/* Command a entropy queue flush and wait for it to finish */
+	random_kthread_control = 1;
+	while (random_kthread_control)
+		pause("-", hz/10);
+
+#if 0
+#if defined(RANDOM_YARROW)
+	random_yarrow_reseed();
+#endif
+#if defined(RANDOM_FORTUNA)
+	random_fortuna_reseed();
+#endif
+#endif
+}
+
+/* ARGSUSED */
+RANDOM_CHECK_UINT(harvestmask, 0, ((1<<RANDOM_ENVIRONMENTAL_END) - 1));
+
+/* ARGSUSED */
+static int
+random_print_harvestmask(SYSCTL_HANDLER_ARGS)
+{
+	struct sbuf sbuf;
+	int error, i;
+
+	error = sysctl_wire_old_buffer(req, 0);
+	if (error == 0) {
+		sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
+		for (i = 31; i >= 0; i--)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list