From: Vladimír Čunát Date: Fri, 4 Aug 2017 06:22:51 +0000 (+0200) Subject: utils: fix seeding of the random generator X-Git-Tag: v1.3.3~3^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3123afd468c0e7a3544c885fda8364a7d04d5d7f;p=thirdparty%2Fknot-resolver.git utils: fix seeding of the random generator 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. --- diff --git a/NEWS b/NEWS index 185173f89..28bc2b7c4 100644 --- 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 ------------ diff --git a/lib/utils.c b/lib/utils.c index ab0189c1f..66b71ff35 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -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));