Module Name:    src
Committed By:   riastradh
Date:           Wed Feb 17 00:43:43 UTC 2016

Modified Files:
        src/sys/kern: kern_rndq.c
        src/sys/sys: rndsource.h

Log Message:
Add rnd_add_data_sync for synchronous on-demand rndsource callbacks.

Avoids lock recursion in rndsinks:

rndsink user holds lock
calls rndsink_request
calls rnd_getmore
calls an rndsource callback
calls rnd_add_data
calls rnd_process_events
calls rndsinks_distribute
calls rndsink callback
acquires rndsink user lock.

This can happen only before the rnd_process_events softint is
established, but that's enough to cause a problem and is the main
reason why all our HWRNG drivers are so byzantine (soon to be
fixed!).

ok tls


To generate a diff of this commit:
cvs rdiff -u -r1.75 -r1.76 src/sys/kern/kern_rndq.c
cvs rdiff -u -r1.4 -r1.5 src/sys/sys/rndsource.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_rndq.c
diff -u src/sys/kern/kern_rndq.c:1.75 src/sys/kern/kern_rndq.c:1.76
--- src/sys/kern/kern_rndq.c:1.75	Mon Jan 11 14:55:52 2016
+++ src/sys/kern/kern_rndq.c	Wed Feb 17 00:43:42 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_rndq.c,v 1.75 2016/01/11 14:55:52 tls Exp $	*/
+/*	$NetBSD: kern_rndq.c,v 1.76 2016/02/17 00:43:42 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1997-2013 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.75 2016/01/11 14:55:52 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.76 2016/02/17 00:43:42 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -156,7 +156,7 @@ static        void	rnd_intr(void *);
 static	      void	rnd_wake(void *);
 static	      void	rnd_process_events(void);
 static	      void	rnd_add_data_ts(krndsource_t *, const void *const,
-					uint32_t, uint32_t, uint32_t);
+					uint32_t, uint32_t, uint32_t, bool);
 static inline void	rnd_schedule_process(void);
 
 int			rnd_ready = 0;
@@ -299,6 +299,18 @@ rnd_getmore(size_t byteswanted)
 		    rs->name, byteswanted);
 	}
 	mutex_spin_exit(&rnd_global.lock);
+
+	/*
+	 * Assume some callback is likely to have entered entropy
+	 * synchronously.  In that case, we may need to distribute
+	 * entropy to waiters.  Do that, if we can do it
+	 * asynchronously.  (Otherwise we may end up trying to
+	 * distribute to the very rndsink that is trying to get more
+	 * entropy in the first place, leading to lock recursion in
+	 * that rndsink's callback.)
+	 */
+	if (__predict_true(rnd_process))
+		rnd_schedule_process();
 }
 
 /*
@@ -789,7 +801,7 @@ _rnd_add_uint32(krndsource_t *rs, uint32
 	 */
 	entropy = rnd_estimate(rs, ts, val);
 
-	rnd_add_data_ts(rs, &val, sizeof(val), entropy, ts);
+	rnd_add_data_ts(rs, &val, sizeof(val), entropy, ts, true);
 }
 
 void
@@ -813,7 +825,7 @@ _rnd_add_uint64(krndsource_t *rs, uint64
 	 */
 	entropy = rnd_estimate(rs, ts, (uint32_t)(val & (uint64_t)0xffffffff));
 
-	rnd_add_data_ts(rs, &val, sizeof(val), entropy, ts);
+	rnd_add_data_ts(rs, &val, sizeof(val), entropy, ts, true);
 }
 
 void
@@ -831,13 +843,22 @@ rnd_add_data(krndsource_t *rs, const voi
 		rndpool_add_data(&rnd_global.pool, data, len, entropy);
 		mutex_spin_exit(&rnd_global.lock);
 	} else {
-		rnd_add_data_ts(rs, data, len, entropy, rnd_counter());
+		rnd_add_data_ts(rs, data, len, entropy, rnd_counter(), true);
 	}
 }
 
+void
+rnd_add_data_sync(krndsource_t *rs, const void *data, uint32_t len,
+    uint32_t entropy)
+{
+
+	KASSERT(rs != NULL);
+	rnd_add_data_ts(rs, data, len, entropy, rnd_counter(), false);
+}
+
 static void
 rnd_add_data_ts(krndsource_t *rs, const void *const data, uint32_t len,
-    uint32_t entropy, uint32_t ts)
+    uint32_t entropy, uint32_t ts, bool schedule)
 {
 	rnd_sample_t *state = NULL;
 	const uint8_t *p = data;
@@ -942,8 +963,9 @@ rnd_add_data_ts(krndsource_t *rs, const 
 	}
 	mutex_spin_exit(&rnd_samples.lock);
 
-	/* Cause processing of queued samples */
-	rnd_schedule_process();
+	/* Cause processing of queued samples, if caller wants it.  */
+	if (schedule)
+		rnd_schedule_process();
 }
 
 static int

Index: src/sys/sys/rndsource.h
diff -u src/sys/sys/rndsource.h:1.4 src/sys/sys/rndsource.h:1.5
--- src/sys/sys/rndsource.h:1.4	Tue Feb 16 23:07:58 2016
+++ src/sys/sys/rndsource.h	Wed Feb 17 00:43:43 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: rndsource.h,v 1.4 2016/02/16 23:07:58 riastradh Exp $	*/
+/*	$NetBSD: rndsource.h,v 1.5 2016/02/17 00:43:43 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -89,6 +89,8 @@ void		_rnd_add_uint32(krndsource_t *, ui
 void		_rnd_add_uint64(krndsource_t *, uint64_t);
 void		rnd_add_data(krndsource_t *, const void *const, uint32_t,
 		    uint32_t);
+void		rnd_add_data_sync(krndsource_t *, const void *, uint32_t,
+		    uint32_t);
 void		rnd_attach_source(krndsource_t *, const char *,
 		    uint32_t, uint32_t);
 void		rnd_detach_source(krndsource_t *);

Reply via email to