From b89446bb33fbe6b9820efdbea62433657757a03f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Jan 2014 13:07:28 +0100 Subject: [PATCH] util: introduce new dev_urandom() call that is like random_bytes() but doesn't fall back to PRNG --- src/shared/util.c | 38 +++++++++++++++++++++++++------------- src/shared/util.h | 1 + 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/shared/util.c b/src/shared/util.c index 945f1525a..f452431c6 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2255,25 +2255,37 @@ char* dirname_malloc(const char *path) { return dir; } -void random_bytes(void *p, size_t n) { - static bool srand_called = false; +int dev_urandom(void *p, size_t n) { _cleanup_close_ int fd; ssize_t k; - uint8_t *q; fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) - goto fallback; + return errno == ENOENT ? -ENOSYS : -errno; k = loop_read(fd, p, n, true); - if (k < 0 || (size_t) k != n) - goto fallback; + if (k < 0) + return (int) k; + if ((size_t) k != n) + return -EIO; - return; + return 0; +} -fallback: +void random_bytes(void *p, size_t n) { + static bool srand_called = false; + uint8_t *q; + int r; + + r = dev_urandom(p, n); + if (r >= 0) + return; + + /* If some idiot made /dev/urandom unavailable to us, he'll + * get a PRNG instead. */ if (!srand_called) { + unsigned x = 0; #ifdef HAVE_SYS_AUXV_H /* The kernel provides us with a bit of entropy in @@ -2285,16 +2297,16 @@ fallback: auxv = (void*) getauxval(AT_RANDOM); if (auxv) - srand(*(unsigned*) auxv); - else + x ^= *(unsigned*) auxv; #endif - srand(time(NULL) + gettid()); + x ^= (unsigned) now(CLOCK_REALTIME); + x ^= (unsigned) gettid(); + + srand(x); srand_called = true; } - /* If some idiot made /dev/urandom unavailable to us, he'll - * get a PRNG instead. */ for (q = p; q < (uint8_t*) p + n; q ++) *q = rand(); } diff --git a/src/shared/util.h b/src/shared/util.h index 1169864c3..117855de8 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -272,6 +272,7 @@ int make_stdio(int fd); int make_null_stdio(void); int make_console_stdio(void); +int dev_urandom(void *p, size_t n); void random_bytes(void *p, size_t n); static inline uint64_t random_u64(void) { -- 2.30.2