Source-Changes-HG archive

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

[src/trunk]: src/sys Fix two problems that could cause /dev/random to not wak...



details:   https://anonhg.NetBSD.org/src/rev/cffbf8e3a4f0
branches:  trunk
changeset: 779332:cffbf8e3a4f0
user:      tls <tls%NetBSD.org@localhost>
date:      Sat May 19 16:00:41 2012 +0000

description:
Fix two problems that could cause /dev/random to not wake up readers when entropy became available.

diffstat:

 sys/dev/rndpseudo.c   |  23 +++++++++++++----------
 sys/kern/subr_cprng.c |  46 +++++++++++++++++++++++++++++-----------------
 2 files changed, 42 insertions(+), 27 deletions(-)

diffs (133 lines):

diff -r c92cc5ef9467 -r cffbf8e3a4f0 sys/dev/rndpseudo.c
--- a/sys/dev/rndpseudo.c       Sat May 19 15:17:35 2012 +0000
+++ b/sys/dev/rndpseudo.c       Sat May 19 16:00:41 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rndpseudo.c,v 1.9 2012/04/20 21:57:33 tls Exp $        */
+/*     $NetBSD: rndpseudo.c,v 1.10 2012/05/19 16:00:41 tls 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.9 2012/04/20 21:57:33 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.10 2012/05/19 16:00:41 tls Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -309,14 +309,23 @@
                /* XXX is this _really_ what's wanted? */
                if (ctx->hard) {
                        n = MIN(want, strength - ctx->bytesonkey);
-                       ctx->bytesonkey += n;
+                       if (n < 1) {
+                           cprng_strong_deplete(cprng);
+                           n = MIN(want, strength);
+                           ctx->bytesonkey = 0;
+                           membar_producer();
+                       }
                } else {
                        n = want;
                }
 
                nread = cprng_strong(cprng, bf, n,
                                     (fp->f_flag & FNONBLOCK) ? FNONBLOCK : 0);
-               if (nread != n) {
+
+               if (ctx->hard && nread > 0) {
+                       atomic_add_int(&ctx->bytesonkey, nread);
+               }
+               if (nread < 1) {
                        if (fp->f_flag & FNONBLOCK) {
                                ret = EWOULDBLOCK;
                        } else {
@@ -331,12 +340,6 @@
                }
        }
 out:
-       if (ctx->bytesonkey >= strength) {
-               /* Force reseed of underlying DRBG (prediction resistance) */
-               cprng_strong_deplete(cprng);
-               ctx->bytesonkey = 0;
-       }
-
        pool_cache_put(rp_pc, bf);
        return (ret);
 }
diff -r c92cc5ef9467 -r cffbf8e3a4f0 sys/kern/subr_cprng.c
--- a/sys/kern/subr_cprng.c     Sat May 19 15:17:35 2012 +0000
+++ b/sys/kern/subr_cprng.c     Sat May 19 16:00:41 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_cprng.c,v 1.8 2012/04/17 02:50:39 tls Exp $ */
+/*     $NetBSD: subr_cprng.c,v 1.9 2012/05/19 16:00:41 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.8 2012/04/17 02:50:39 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.9 2012/05/19 16:00:41 tls Exp $");
 
 void
 cprng_init(void)
@@ -144,6 +144,9 @@
 #ifdef RND_VERBOSE
            printf("cprng: sink %s cprng busy, no reseed\n", c->reseed.name);
 #endif
+           if (c->flags & CPRNG_USE_CV) {      /* XXX if flags change? */
+               cv_broadcast(&c->cv);
+           }
            return;
        }
 
@@ -240,23 +243,32 @@
                                      "failed.", c->name);
                        }
                } else {
-                       if (!(flags & FNONBLOCK) && 
-                            (c->flags & CPRNG_USE_CV)) {
-                               int wr;
+                       int wr;
 
+                       do {
                                cprng_strong_sched_reseed(c);
-                               do {
-                                       wr = cv_wait_sig(&c->cv, &c->mtx);
-                                       if (wr == ERESTART) {
-                                               mutex_exit(&c->mtx);
-                                               return 0;
-                                       }
-                               } while (nist_ctr_drbg_generate(&c->drbg, p,
-                                                               len, &cc,
-                                                               sizeof(cc)));
-                       } else {
-                               len = 0;
-                       }
+                               if ((flags & FNONBLOCK) ||
+                                   !(c->flags & CPRNG_USE_CV)) {
+                                       len = 0;
+                                       break;
+                               }
+                       /*
+                        * XXX There's a race with the cv_broadcast
+                        * XXX in cprng_strong_sched_reseed, because
+                        * XXX of the use of tryenter in that function.
+                        * XXX This "timedwait" hack works around it,
+                        * XXX at the expense of occasionaly polling
+                        * XXX for success on a /dev/random rekey.
+                        */
+                               wr = cv_timedwait_sig(&c->cv, &c->mtx,
+                                                     mstohz(100));
+                               if (wr == ERESTART) {
+                                       mutex_exit(&c->mtx);
+                                       return 0;
+                               }
+                       } while (nist_ctr_drbg_generate(&c->drbg, p,
+                                                       len, &cc,
+                                                       sizeof(cc)));
                }
        }
 



Home | Main Index | Thread Index | Old Index