From: Lennart Poettering Date: Thu, 30 Oct 2014 14:27:53 +0000 (+0100) Subject: util: don't block on getrandom() X-Git-Tag: v218~661 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=97768fc5746ea97cb2d3ac6854b4fc7ce1c14f24;hp=e3c72c21d62aadabf4df436c3e2c7219eeeccc1c util: don't block on getrandom() --- diff --git a/src/shared/missing.h b/src/shared/missing.h index 85d3fec33..7725e4729 100644 --- a/src/shared/missing.h +++ b/src/shared/missing.h @@ -149,6 +149,14 @@ static inline int getrandom(void *buffer, size_t count, unsigned flags) { } #endif +#ifndef GRND_NONBLOCK +#define GRND_NONBLOCK 0x0001 +#endif + +#ifndef GRND_RANDOM +#define GRND_RANDOM 0x0002 +#endif + #ifndef BTRFS_IOCTL_MAGIC #define BTRFS_IOCTL_MAGIC 0x94 #endif diff --git a/src/shared/util.c b/src/shared/util.c index ceafba86a..1d67abe58 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2470,10 +2470,17 @@ int dev_urandom(void *p, size_t n) { int r, fd; ssize_t k; - /* Use the syscall unless we know we don't have it, or when - * the requested size is too large for it. */ + /* Gathers some randomness from the kernel. This call will + * never block, and will always return some data from the + * kernel, regardless if the random pool is fully initialized + * or not. It thus makes no guarantee for the quality of the + * returned entropy, but is good enough for or usual usecases + * of seeding the hash functions for hashtable */ + + /* Use the getrandom() syscall unless we know we don't have + * it, or when the requested size is too large for it. */ if (have_syscall != 0 || (size_t) (int) n != n) { - r = getrandom(p, n, 0); + r = getrandom(p, n, GRND_NONBLOCK); if (r == (int) n) { have_syscall = true; return 0; @@ -2481,8 +2488,17 @@ int dev_urandom(void *p, size_t n) { if (r < 0) { if (errno == ENOSYS) - /* we lack the syscall, continue with reading from /dev/urandom */ + /* we lack the syscall, continue with + * reading from /dev/urandom */ have_syscall = false; + else if (errno == EAGAIN) + /* not enough entropy for now. Let's + * remember to use the syscall the + * next time, again, but also read + * from /dev/urandom for now, which + * doesn't care about the current + * amount of entropy. */ + have_syscall = true; else return -errno; } else