Source-Changes-HG archive

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

[src/netbsd-6]: src/sys Pull up following revision(s) (requested by tls in ti...



details:   https://anonhg.NetBSD.org/src/rev/76b33defca29
branches:  netbsd-6
changeset: 774016:76b33defca29
user:      riz <riz%NetBSD.org@localhost>
date:      Thu Apr 19 19:59:10 2012 +0000

description:
Pull up following revision(s) (requested by tls in ticket #185):
        sys/kern/subr_cprng.c: revision 1.6
        sys/kern/subr_cprng.c: revision 1.7
        sys/lib/libkern/arc4random.c: revision 1.32
        sys/kern/kern_rndq.c: revision 1.2
        sys/dev/rndpseudo.c: revision 1.7
        sys/sys/rnd.h: revision 1.30
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.
Fix LOCKDEBUG problems pointed out by drochner@
1) Lock ordering in cprng_strong_destroy had us take a spin mutex then
   an adaptive mutex.  Can't do that.  Reordering this requires changing
   cprng_strong_reseed to tryenter the cprng's own mutex and skip the
   reseed on failure, or we could deadlock.
2) Can't free memory with a valid mutex in it.
reorder initialization to improve error handling in case the system
runs out of file descriptors, avoids LOCKDEBUG panic due to double
mutex initialization

diffstat:

 sys/dev/rndpseudo.c          |  13 ++++++-------
 sys/kern/kern_rndq.c         |  32 +++++++++++++++++++++++++-------
 sys/kern/subr_cprng.c        |  17 +++++++++++++----
 sys/lib/libkern/arc4random.c |   7 ++++++-
 sys/sys/rnd.h                |   3 ++-
 5 files changed, 52 insertions(+), 20 deletions(-)

diffs (277 lines):

diff -r d04ed28b7c30 -r 76b33defca29 sys/dev/rndpseudo.c
--- a/sys/dev/rndpseudo.c       Wed Apr 18 19:56:34 2012 +0000
+++ b/sys/dev/rndpseudo.c       Thu Apr 19 19:59:10 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rndpseudo.c,v 1.6 2011/12/20 13:42:19 apb Exp $        */
+/*     $NetBSD: rndpseudo.c,v 1.6.2.1 2012/04/19 19:59:11 riz Exp $    */
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.6 2011/12/20 13:42:19 apb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.6.2.1 2012/04/19 19:59:11 riz Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -213,15 +213,14 @@
            default:
                return ENXIO;
        }
-       ctx = pool_cache_get(rp_cpc, PR_WAITOK);
-       ctx->cprng = NULL;
-       ctx->hard = hard;
-       mutex_init(&ctx->interlock, MUTEX_DEFAULT, IPL_NONE);
-       
+       ctx = pool_cache_get(rp_cpc, PR_WAITOK);        
        if ((error = fd_allocfile(&fp, &fd)) != 0) {
            pool_cache_put(rp_cpc, ctx);
            return error;
        }
+       ctx->cprng = NULL;
+       ctx->hard = hard;
+       mutex_init(&ctx->interlock, MUTEX_DEFAULT, IPL_NONE);
 
        return fd_clone(fp, fd, flag, &rnd_fileops, ctx);
 }
diff -r d04ed28b7c30 -r 76b33defca29 sys/kern/kern_rndq.c
--- a/sys/kern/kern_rndq.c      Wed Apr 18 19:56:34 2012 +0000
+++ b/sys/kern/kern_rndq.c      Thu Apr 19 19:59:10 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.1.2.1 2012/04/19 19:59:10 riz 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.1.2.1 2012/04/19 19:59:10 riz 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 d04ed28b7c30 -r 76b33defca29 sys/kern/subr_cprng.c
--- a/sys/kern/subr_cprng.c     Wed Apr 18 19:56:34 2012 +0000
+++ b/sys/kern/subr_cprng.c     Thu Apr 19 19:59:10 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.5.2.1 2012/04/19 19:59:10 riz 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.5.2.1 2012/04/19 19:59:10 riz 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);
        }
 }
 
@@ -89,7 +90,10 @@
        uint8_t key[NIST_BLOCK_KEYLEN_BYTES];
        uint32_t cc = cprng_counter();
 
-       mutex_enter(&c->mtx);
+       if (!mutex_tryenter(&c->mtx)) {
+           return;
+       }
+
        if (c->reseed.len != sizeof(key)) {
                panic("cprng_strong_reseed: bad entropy length %d "
                      " (expected %d)", (int)c->reseed.len, (int)sizeof(key));
@@ -123,6 +127,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);
@@ -267,6 +272,7 @@
 cprng_strong_destroy(cprng_strong_t *c)
 {
        mutex_enter(&c->mtx);
+       mutex_spin_enter(&c->reseed.mtx);
 
        if (c->flags & CPRNG_USE_CV) {
                KASSERT(!cv_has_waiters(&c->cv));
@@ -277,6 +283,9 @@
        if (c->reseed_pending) {
                rndsink_detach(&c->reseed);
        }
+       mutex_spin_exit(&c->reseed.mtx);
+       mutex_destroy(&c->reseed.mtx);
+
        nist_ctr_drbg_destroy(&c->drbg);
 
        mutex_exit(&c->mtx);
diff -r d04ed28b7c30 -r 76b33defca29 sys/lib/libkern/arc4random.c
--- a/sys/lib/libkern/arc4random.c      Wed Apr 18 19:56:34 2012 +0000
+++ b/sys/lib/libkern/arc4random.c      Thu Apr 19 19:59:10 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.31.2.1 2012/04/19 19:59:10 riz 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 d04ed28b7c30 -r 76b33defca29 sys/sys/rnd.h
--- a/sys/sys/rnd.h     Wed Apr 18 19:56:34 2012 +0000
+++ b/sys/sys/rnd.h     Thu Apr 19 19:59:10 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.29.2.1 2012/04/19 19:59:11 riz 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