summaryrefslogtreecommitdiff
path: root/src/shared/util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-10-29 17:06:32 +0100
committerLennart Poettering <lennart@poettering.net>2014-10-29 17:06:32 +0100
commit539618a0ddc2dc7f0fbe28de2ae0e07b34c81e60 (patch)
tree23a4a87b839413ee39636eb116b5316571c88878 /src/shared/util.c
parentd0159fdc7a1009027f019f763106aa13256cf030 (diff)
util: make use of the new getrandom() syscall if it is available when needing entropy
Doesn't require an fd, and could be a bit faster, so let's make use of it, if it is available.
Diffstat (limited to 'src/shared/util.c')
-rw-r--r--src/shared/util.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/shared/util.c b/src/shared/util.c
index 4143f6d643..ceafba86af 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -2466,14 +2466,37 @@ char* dirname_malloc(const char *path) {
}
int dev_urandom(void *p, size_t n) {
- _cleanup_close_ int fd;
+ static int have_syscall = -1;
+ 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. */
+ if (have_syscall != 0 || (size_t) (int) n != n) {
+ r = getrandom(p, n, 0);
+ if (r == (int) n) {
+ have_syscall = true;
+ return 0;
+ }
+
+ if (r < 0) {
+ if (errno == ENOSYS)
+ /* we lack the syscall, continue with reading from /dev/urandom */
+ have_syscall = false;
+ else
+ return -errno;
+ } else
+ /* too short read? */
+ return -EIO;
+ }
+
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return errno == ENOENT ? -ENOSYS : -errno;
k = loop_read(fd, p, n, true);
+ safe_close(fd);
+
if (k < 0)
return (int) k;
if ((size_t) k != n)