summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-10-30 15:27:53 +0100
committerAnthony G. Basile <blueness@gentoo.org>2014-10-31 12:02:25 -0400
commiteaa45759c706b458b60a3d951e469dc882def9e4 (patch)
tree5d52964c0be6ef2c5559df83758d0958cdf9a9e5 /src
parentd21fc3fc8e550bbffcf575398d614f657231c4a3 (diff)
util: don't block on getrandom()
Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
Diffstat (limited to 'src')
-rw-r--r--src/shared/missing.h8
-rw-r--r--src/shared/util.c24
2 files changed, 28 insertions, 4 deletions
diff --git a/src/shared/missing.h b/src/shared/missing.h
index 3cd90e39bd..9f6177511e 100644
--- a/src/shared/missing.h
+++ b/src/shared/missing.h
@@ -57,6 +57,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 2080d77e05..d58b9f4bed 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -689,10 +689,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;
@@ -700,8 +707,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