rand/noise.c (noise_devrandom): Fix reading from the kernel random device.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 13 Jul 2013 15:34:40 +0000 (16:34 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 9 Mar 2014 01:04:52 +0000 (01:04 +0000)
It was, unfortunately, filled with badgers.

  * Don't take short reads for an answer.  Loop until the read actually
    fails, or we've filled the buffer.

  * If we didn't actually read enough to fill the buffer, then don't
    return success!  The fallback collectors will engage and hopefully
    save our bacon.

rand/noise.c

index 6ab1070..00f036a 100644 (file)
@@ -156,6 +156,7 @@ int noise_devrandom(rand_pool *r)
   int fd;
   octet buf[RAND_POOLSZ];
   ssize_t len;
+  size_t n = 0;
   int ret = 0;
 
   /* --- Be nice to other clients of the random device --- *
@@ -169,11 +170,13 @@ int noise_devrandom(rand_pool *r)
   if ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
       (fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
       (fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) {
-    if ((len = read(fd, buf, sizeof(buf))) > 0) {
-      rand_add(r, buf, len, len * 8);
-      BURN(buf);
-      ret = 1;
+    while (n < sizeof(buf)) {
+      if ((len = read(fd, buf + n, sizeof(buf) - n)) <= 0) break;
+      n += len;
     }
+    rand_add(r, buf, n, n * 8);
+    BURN(buf);
+    if (n == sizeof(buf)) ret = 1;
     close(fd);
   }
   noise_timer(r);