Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add rnd_add_data_sync for synchronous on-demand rndsourc...



details:   https://anonhg.NetBSD.org/src/rev/07634b9cac71
branches:  trunk
changeset: 343615:07634b9cac71
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Wed Feb 17 00:43:42 2016 +0000

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

diffstat:

 sys/kern/kern_rndq.c |  40 +++++++++++++++++++++++++++++++---------
 sys/sys/rndsource.h  |   4 +++-
 2 files changed, 34 insertions(+), 10 deletions(-)

diffs (119 lines):

diff -r 4cea42665893 -r 07634b9cac71 sys/kern/kern_rndq.c
--- a/sys/kern/kern_rndq.c      Wed Feb 17 00:01:23 2016 +0000
+++ b/sys/kern/kern_rndq.c      Wed Feb 17 00:43:42 2016 +0000
@@ -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_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 @@
                    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 @@
         */
        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 @@
         */
        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 @@
                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 @@
        }
        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
diff -r 4cea42665893 -r 07634b9cac71 sys/sys/rndsource.h
--- a/sys/sys/rndsource.h       Wed Feb 17 00:01:23 2016 +0000
+++ b/sys/sys/rndsource.h       Wed Feb 17 00:43:42 2016 +0000
@@ -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_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 *);



Home | Main Index | Thread Index | Old Index