Source-Changes-HG archive

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

[src/trunk]: src/sys Add a spin mutex to the rndsink structure; it is used to...



details:   https://anonhg.NetBSD.org/src/rev/d5fa9839e4d6
branches:  trunk
changeset: 778722:d5fa9839e4d6
user:      tls <tls%NetBSD.org@localhost>
date:      Tue Apr 10 14:02:27 2012 +0000

description:
Add a spin mutex to the rndsink structure; it is used to avoid lock
ordering and sleep-holding-locks problems when rekeying, and thus
to avoid a nasty race between cprng destruction and reseeding.

diffstat:

 sys/kern/kern_rndq.c         |  32 +++++++++++++++++++++++++-------
 sys/kern/subr_cprng.c        |  11 ++++++++---
 sys/lib/libkern/arc4random.c |   7 ++++++-
 sys/sys/rnd.h                |   3 ++-
 4 files changed, 41 insertions(+), 12 deletions(-)

diffs (226 lines):

diff -r cf55de09dcc4 -r d5fa9839e4d6 sys/kern/kern_rndq.c
--- a/sys/kern/kern_rndq.c      Tue Apr 10 13:58:52 2012 +0000
+++ b/sys/kern/kern_rndq.c      Tue Apr 10 14:02:27 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_rndq.c,v 1.1 2012/02/02 19:43:07 tls Exp $        */
+/*     $NetBSD: kern_rndq.c,v 1.2 2012/04/10 14:02:27 tls Exp $        */
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.1 2012/02/02 19:43:07 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.2 2012/04/10 14:02:27 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
@@ -109,13 +109,17 @@
 SIMPLEQ_HEAD(, _rnd_sample_t)  rnd_samples;
 kmutex_t                       rnd_mtx;
 
+
 /*
  * Entropy sinks: usually other generators waiting to be rekeyed.
  *
  * A sink's callback MUST NOT re-add the sink to the list, or
- * list corruption will occur.
+ * list corruption will occur.  The list is protected by the
+ * rndsink_mtx, which must be released before calling any sink's
+ * callback.
  */
 TAILQ_HEAD(, rndsink)          rnd_sinks;
+kmutex_t                       rndsink_mtx;
 
 /*
  * Memory pool for sample buffers
@@ -215,6 +219,7 @@
        /*
         * First, take care of in-kernel consumers needing rekeying.
         */
+       mutex_spin_enter(&rndsink_mtx);
        TAILQ_FOREACH_SAFE(sink, &rnd_sinks, tailq, tsink) {
                if ((sink->len + RND_ENTROPY_THRESHOLD) * 8 <
                        rndpool_get_entropy_count(&rnd_pool)) {
@@ -225,11 +230,16 @@
                                panic("could not extract estimated "
                                      "entropy from pool");
                        }
+                       /* Skip if busy, else mark in-progress */
+                       if (!mutex_tryenter(&sink->mtx)) {
+                           continue;
+                       }
                        /* Move this sink to the list of pending callbacks */
                        TAILQ_REMOVE(&rnd_sinks, sink, tailq);
                        TAILQ_INSERT_HEAD(&sunk, sink, tailq);
                }
        }
+       mutex_spin_exit(&rndsink_mtx);
                
        /*
         * If we still have enough new bits to do something, feed userspace.
@@ -261,6 +271,7 @@
 #endif
                sink->cb(sink->arg);
                TAILQ_REMOVE(&sunk, sink, tailq);
+               mutex_spin_exit(&sink->mtx);
        }
 }
 
@@ -362,6 +373,7 @@
                return;
 
        mutex_init(&rnd_mtx, MUTEX_DEFAULT, IPL_VM);
+       mutex_init(&rndsink_mtx, MUTEX_DEFAULT, IPL_VM);
 
        callout_init(&rnd_callout, CALLOUT_MPSAFE);
        callout_setfunc(&rnd_callout, rnd_timeout, NULL);
@@ -962,9 +974,12 @@
        printf("rnd: entropy sink \"%s\" wants %d bytes of data.\n",
               rs->name, (int)rs->len);
 #endif
-       mutex_spin_enter(&rndpool_mtx);
+
+       KASSERT(mutex_owned(&rs->mtx));
+
+       mutex_spin_enter(&rndsink_mtx);
        TAILQ_INSERT_TAIL(&rnd_sinks, rs, tailq);
-       mutex_spin_exit(&rndpool_mtx);
+       mutex_spin_exit(&rndsink_mtx);
        mutex_spin_enter(&rnd_mtx);
        if (rnd_timeout_pending == 0) {
                rnd_timeout_pending = 1;
@@ -980,13 +995,16 @@
 #ifdef RND_VERBOSE
        printf("rnd: entropy sink \"%s\" no longer wants data.\n", rs->name);
 #endif
-       mutex_spin_enter(&rndpool_mtx);
+
+       KASSERT(mutex_owned(&rs->mtx));
+
+       mutex_spin_enter(&rndsink_mtx);
        TAILQ_FOREACH_SAFE(sink, &rnd_sinks, tailq, tsink) {
                if (sink == rs) {
                        TAILQ_REMOVE(&rnd_sinks, rs, tailq);
                }
        }
-       mutex_spin_exit(&rndpool_mtx);
+       mutex_spin_exit(&rndsink_mtx);
 }
 
 void
diff -r cf55de09dcc4 -r d5fa9839e4d6 sys/kern/subr_cprng.c
--- a/sys/kern/subr_cprng.c     Tue Apr 10 13:58:52 2012 +0000
+++ b/sys/kern/subr_cprng.c     Tue Apr 10 14:02:27 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_cprng.c,v 1.5 2011/12/17 20:05:39 tls Exp $ */
+/*     $NetBSD: subr_cprng.c,v 1.6 2012/04/10 14:02:28 tls Exp $ */
 
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
@@ -46,7 +46,7 @@
 
 #include <sys/cprng.h>
 
-__KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.5 2011/12/17 20:05:39 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.6 2012/04/10 14:02:28 tls Exp $");
 
 void
 cprng_init(void)
@@ -75,10 +75,11 @@
 cprng_strong_sched_reseed(cprng_strong_t *const c)
 {
        KASSERT(mutex_owned(&c->mtx));
-       if (!(c->reseed_pending)) {
+       if (!(c->reseed_pending) && mutex_tryenter(&c->reseed.mtx)) {
                c->reseed_pending = 1;
                c->reseed.len = NIST_BLOCK_KEYLEN_BYTES;
                rndsink_attach(&c->reseed);
+               mutex_spin_exit(&c->reseed.mtx);
        }
 }
 
@@ -123,6 +124,7 @@
        c->reseed_pending = 0;
        c->reseed.cb = cprng_strong_reseed;
        c->reseed.arg = c;
+       mutex_init(&c->reseed.mtx, MUTEX_DEFAULT, IPL_VM);
        strlcpy(c->reseed.name, name, sizeof(c->reseed.name));
 
        mutex_init(&c->mtx, MUTEX_DEFAULT, ipl);
@@ -266,6 +268,7 @@
 void
 cprng_strong_destroy(cprng_strong_t *c)
 {
+       mutex_spin_enter(&c->reseed.mtx);
        mutex_enter(&c->mtx);
 
        if (c->flags & CPRNG_USE_CV) {
@@ -277,6 +280,8 @@
        if (c->reseed_pending) {
                rndsink_detach(&c->reseed);
        }
+       mutex_spin_exit(&c->reseed.mtx);
+
        nist_ctr_drbg_destroy(&c->drbg);
 
        mutex_exit(&c->mtx);
diff -r cf55de09dcc4 -r d5fa9839e4d6 sys/lib/libkern/arc4random.c
--- a/sys/lib/libkern/arc4random.c      Tue Apr 10 13:58:52 2012 +0000
+++ b/sys/lib/libkern/arc4random.c      Tue Apr 10 14:02:27 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: arc4random.c,v 1.31 2012/02/14 18:57:35 njoly Exp $    */
+/*     $NetBSD: arc4random.c,v 1.32 2012/04/10 14:02:28 tls Exp $      */
 
 /*-
  * Copyright (c) 2002, 2011 The NetBSD Foundation, Inc.
@@ -167,7 +167,9 @@
                                    "forcibly rekeying.\n");
                                r = rnd_extract_data(key, ARC4_KEYBYTES,
                                    RND_EXTRACT_ANY);
+                               mutex_spin_enter(&rs.mtx);
                                rndsink_detach(&rs);
+                               mutex_spin_exit(&rs.mtx);
                                callback_pending = 0;
                                goto got_entropy;
                        } else {
@@ -195,11 +197,13 @@
                callback_pending = 0;
        } else if (!callback_pending) {
                callback_pending = 1;
+               mutex_spin_enter(&rs.mtx);
                strlcpy(rs.name, "arc4random", sizeof(rs.name));
                rs.cb = arc4_randrekey;
                rs.arg = &rs;
                rs.len = ARC4_KEYBYTES;
                rndsink_attach(&rs);
+               mutex_spin_exit(&rs.mtx);
        }
 #endif
        /*
@@ -260,6 +264,7 @@
        int n;
 
        mutex_init(&arc4_mtx, MUTEX_DEFAULT, IPL_VM);
+       mutex_init(&rs.mtx, MUTEX_DEFAULT, IPL_VM);
        arc4_i = arc4_j = 0;
        for (n = 0; n < 256; n++)
                arc4_sbox[n] = (u_int8_t) n;
diff -r cf55de09dcc4 -r d5fa9839e4d6 sys/sys/rnd.h
--- a/sys/sys/rnd.h     Tue Apr 10 13:58:52 2012 +0000
+++ b/sys/sys/rnd.h     Tue Apr 10 14:02:27 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rnd.h,v 1.29 2012/02/02 19:43:08 tls Exp $     */
+/*     $NetBSD: rnd.h,v 1.30 2012/04/10 14:02:28 tls Exp $     */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -129,6 +129,7 @@
 
 typedef struct rndsink {
         TAILQ_ENTRY(rndsink) tailq;     /* the queue */
+       kmutex_t        mtx;            /* lock to seed or unregister */
         void            (*cb)(void *);  /* callback function when ready */
         void            *arg;           /* callback function argument */
         char            name[16];       /* sink name */



Home | Main Index | Thread Index | Old Index