]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
utils: fix seeding of the random generator
authorVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 4 Aug 2017 06:22:51 +0000 (08:22 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 4 Aug 2017 12:12:34 +0000 (14:12 +0200)
If the fread didn't read all in one go, the buffer was being repeatedly
overwritten from the start instead of continuing the read :-/
I also changed the overall approach in some respects.

NEWS
lib/utils.c

diff --git a/NEWS b/NEWS
index 185173f89106787b52623ac79ed2e0d063dc8412..28bc2b7c47ab0d7175856c1e3fe9507854e9d22f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Knot Resolver 1.3.3 (2017-0_-__)
 Bugfixes
 --------
 - iterate: skip RRSIGs with bad label count instead of immediate SERVFAIL
+- utils: fix possible incorrect seeding of the random generator
 
 Improvements
 ------------
index ab0189c1f936b61919a0244f365b153fc1c30295..66b71ff35a3644eaf377ec2716937ccc4a7dae3a 100644 (file)
@@ -127,16 +127,25 @@ char* kr_strcatdup(unsigned n, ...)
        return result;
 }
 
-static int seed_file(FILE *fp, char *buf, size_t buflen)
+static int seed_file(const char *fname, char *buf, size_t buflen)
 {
+       auto_fclose FILE *fp = fopen(fname, "r");
        if (!fp) {
-               return -1;
-       }
-       /* Read whole buffer even if interrupted */
-       ssize_t readb = 0;
-       while (!ferror(fp) && readb < buflen) {
-               readb += fread(buf, 1, buflen - readb, fp);
+               return kr_error(EINVAL);
        }
+       /* Disable buffering to conserve randomness but ignore failing to do so. */
+       setvbuf(fp, NULL, _IONBF, 0);
+       do {
+               if (feof(fp)) {
+                       return kr_error(ENOENT);
+               }
+               if (ferror(fp)) {
+                       return kr_error(ferror(fp));
+               }
+               if (fread(buf, buflen, 1, fp)) { /* read in one chunk for simplicity */
+                       return kr_ok();
+               }
+       } while (true);
        return 0;
 }
 
@@ -147,13 +156,13 @@ static int randseed(char *buf, size_t buflen)
         "/dev/srandom", "/dev/urandom", "/dev/random", NULL
     };
     for (unsigned i = 0; filenames[i]; ++i) {
-        auto_fclose FILE *fp = fopen(filenames[i], "r");
-        if (seed_file(fp, buf, buflen) == 0) {
+        if (seed_file(filenames[i], buf, buflen) == 0) {
             return 0;
         }
     }
 
     /* Seed from time, this is not going to be secure. */
+    kr_log_error("failed to obtain randomness, falling back to current time\n");
     struct timeval tv;
     gettimeofday(&tv, NULL);
     memcpy(buf, &tv, buflen < sizeof(tv) ? buflen : sizeof(tv));