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 *);