NetBSD-Bugs archive

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

Re: kern/48119 (/dev/random kernel crash)



The following reply was made to PR kern/48119; it has been noted by GNATS.

From: Sergio Lopez <slp%sinrega.org@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: brad.harder%gmail.com@localhost
Subject: Re: kern/48119 (/dev/random kernel crash)
Date: Wed, 28 Aug 2013 07:37:31 +0000

 --tKW2IUtsqtDRztdT
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 rnd_read(rndpseudo.c) assumes cprng_strong will only return 0 when
 processing a non-blocking request, but as the latter can eventually
 sit on cv_wait_sig waiting for entropy, this will also happen when the
 request is interrupted, which is what is happening here.
 
 As as PoC, I've modified (see attached file) cprng_strong to return -1
 when cv_wait_sig is interrupted, and rnd_read to detect this and bail
 out. Probably, it would be better to extend cprng_strong so it returns
 the error code in addition to the number of bytes read.
 
 
 --tKW2IUtsqtDRztdT
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="pr48119.diff"
 
 Index: kern/subr_cprng.c
 ===================================================================
 RCS file: /cvsroot/src/sys/kern/subr_cprng.c,v
 retrieving revision 1.22
 diff -u -r1.22 subr_cprng.c
 --- kern/subr_cprng.c  27 Jul 2013 11:19:09 -0000      1.22
 +++ kern/subr_cprng.c  28 Aug 2013 07:36:29 -0000
 @@ -180,6 +180,7 @@
  size_t
  cprng_strong(struct cprng_strong *cprng, void *buffer, size_t bytes, int 
flags)
  {
 +      int error;
        size_t result;
  
        /* Caller must loop for more than CPRNG_MAX_LEN bytes.  */
 @@ -193,11 +194,16 @@
        } else {
                while (!cprng->cs_ready) {
                        if (ISSET(flags, FNONBLOCK) ||
 -                          !ISSET(cprng->cs_flags, CPRNG_USE_CV) ||
 -                          cv_wait_sig(&cprng->cs_cv, &cprng->cs_lock)) {
 +                          !ISSET(cprng->cs_flags, CPRNG_USE_CV)) {
                                result = 0;
                                goto out;
                        }
 +      
 +                      error = cv_wait_sig(&cprng->cs_cv, &cprng->cs_lock);
 +                      if (error) {
 +                              result = -1;
 +                              goto out;
 +                      }
                }
        }
  
 Index: dev/rndpseudo.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/rndpseudo.c,v
 retrieving revision 1.16
 diff -u -r1.16 rndpseudo.c
 --- dev/rndpseudo.c    21 Jul 2013 22:30:19 -0000      1.16
 +++ dev/rndpseudo.c    28 Aug 2013 07:36:35 -0000
 @@ -375,6 +375,12 @@
                    ((ctx->rc_hard && ISSET(fp->f_flag, FNONBLOCK))?
                        FNONBLOCK : 0));
  
 +              if (n_read == -1) {
 +                      printf("rnd EINTR\n");
 +                      error = EINTR;
 +                      goto out;
 +              }
 +
                /*
                 * Equality will hold unless this is /dev/random, in
                 * which case we get only as many bytes as are left
 
 --tKW2IUtsqtDRztdT--
 


Home | Main Index | Thread Index | Old Index