diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/liboutils/getentropy_linux.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/src/liboutils/getentropy_linux.c b/src/liboutils/getentropy_linux.c index b9312ae..f0e3d40 100644 --- a/src/liboutils/getentropy_linux.c +++ b/src/liboutils/getentropy_linux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getentropy_linux.c,v 1.31 2014/07/21 23:34:54 deraadt Exp $ */ +/* $OpenBSD: getentropy_linux.c,v 1.41 2015/09/11 11:52:55 deraadt Exp $ */ /* * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org> @@ -27,8 +27,8 @@ #include <sys/ioctl.h> #include <sys/resource.h> #include <sys/syscall.h> -#ifdef HAVE_SYS_SYSCTL_H -#include <sys/sysctl.h> +#ifdef SYS__sysctl +#include <linux/sysctl.h> #endif #include <sys/statvfs.h> #include <sys/socket.h> @@ -49,8 +49,8 @@ #include <time.h> #include <openssl/sha.h> +#include <linux/types.h> #include <linux/random.h> -#include <linux/sysctl.h> #ifdef HAVE_GETAUXVAL #include <sys/auxv.h> #endif @@ -74,7 +74,9 @@ int getentropy(void *buf, size_t len); static int gotdata(char *buf, size_t len); +#ifdef SYS_getrandom static int getentropy_getrandom(void *buf, size_t len); +#endif static int getentropy_urandom(void *buf, size_t len); #ifdef SYS__sysctl static int getentropy_sysctl(void *buf, size_t len); @@ -89,15 +91,19 @@ getentropy(void *buf, size_t len) if (len > 256) { errno = EIO; - return -1; + return (-1); } +#ifdef SYS_getrandom /* * Try descriptor-less getrandom() */ ret = getentropy_getrandom(buf, len); if (ret != -1) return (ret); + if (errno != ENOSYS) + return (-1); +#endif /* * Try to get entropy with /dev/urandom @@ -114,7 +120,7 @@ getentropy(void *buf, size_t len) * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID. * sysctl is a failsafe API, so it guarantees a result. This * should work inside a chroot, or when file descriptors are - * exhuasted. + * exhausted. * * However this can fail if the Linux kernel removes support * for sysctl. Starting in 2007, there have been efforts to @@ -180,31 +186,28 @@ gotdata(char *buf, size_t len) for (i = 0; i < len; ++i) any_set |= buf[i]; if (any_set == 0) - return -1; - return 0; + return (-1); + return (0); } +#ifdef SYS_getrandom static int getentropy_getrandom(void *buf, size_t len) { -#if 0 - -/* Hand-definitions until the API becomes commonplace */ -#ifndef SYS__getrandom -#ifdef __LP64__ -#define SYS__getrandom 317 -#else -#define SYS__getrandom 354 -#endif -#endif + int pre_errno = errno; + int ret; if (len > 256) return (-1); - ret = syscall(SYS__getrandom, buf, len, 0); - if (ret == len) - return (0); -#endif - return -1; + do { + ret = syscall(SYS_getrandom, buf, len, 0); + } while (ret == -1 && errno == EINTR); + + if (ret != len) + return (-1); + errno = pre_errno; + return (0); } +#endif static int getentropy_urandom(void *buf, size_t len) @@ -257,11 +260,11 @@ start: close(fd); if (gotdata(buf, len) == 0) { errno = save_errno; - return 0; /* satisfied */ + return (0); /* satisfied */ } nodevrandom: errno = EIO; - return -1; + return (-1); } #ifdef SYS__sysctl @@ -292,11 +295,11 @@ getentropy_sysctl(void *buf, size_t len) } sysctlfailed: errno = EIO; - return -1; + return (-1); } #endif /* SYS__sysctl */ -static int cl[] = { +static const int cl[] = { CLOCK_REALTIME, #ifdef CLOCK_MONOTONIC CLOCK_MONOTONIC, @@ -327,7 +330,7 @@ getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data) SHA512_CTX *ctx = data; SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr)); - return 0; + return (0); } static int @@ -537,8 +540,8 @@ getentropy_fallback(void *buf, size_t len) explicit_bzero(results, sizeof results); if (gotdata(buf, len) == 0) { errno = save_errno; - return 0; /* satisfied */ + return (0); /* satisfied */ } errno = EIO; - return -1; + return (-1); } |