From 539618a0ddc2dc7f0fbe28de2ae0e07b34c81e60 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 29 Oct 2014 17:06:32 +0100 Subject: [PATCH] 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. --- configure.ac | 3 ++- src/shared/missing.h | 15 +++++++++++++++ src/shared/util.c | 25 ++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index f8a95cb9c..82bc7a63f 100644 --- a/configure.ac +++ b/configure.ac @@ -308,7 +308,7 @@ LIBS="$save_LIBS" AC_CHECK_FUNCS([memfd_create]) AC_CHECK_FUNCS([__secure_getenv secure_getenv]) -AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, LO_FLAGS_PARTSCAN], +AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, getrandom, LO_FLAGS_PARTSCAN], [], [], [[ #include #include @@ -316,6 +316,7 @@ AC_CHECK_DECLS([gettid, pivot_root, name_to_handle_at, setns, LO_FLAGS_PARTSCAN] #include #include #include +#include ]]) AC_CHECK_DECLS([IFLA_MACVLAN_FLAGS, diff --git a/src/shared/missing.h b/src/shared/missing.h index bb4f8f23a..5b87e23ee 100644 --- a/src/shared/missing.h +++ b/src/shared/missing.h @@ -140,6 +140,21 @@ static inline int memfd_create(const char *name, unsigned int flags) { } #endif +#ifndef __NR_getrandom +# if defined __x86_64__ +# define __NR_getrandom 278 +# else +# warning "__NR_getrandom unknown for your architecture" +# define __NR_getrandom 0xffffffff +# endif +#endif + +#if !HAVE_DECL_GETRANDOM +static inline int getrandom(void *buffer, size_t count, unsigned flags) { + return syscall(__NR_getrandom, buffer, count, flags); +} +#endif + #ifndef BTRFS_IOCTL_MAGIC #define BTRFS_IOCTL_MAGIC 0x94 #endif diff --git a/src/shared/util.c b/src/shared/util.c index 4143f6d64..ceafba86a 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) -- 2.30.2