From: Mark Wooding Date: Thu, 26 May 2016 08:26:09 +0000 (+0100) Subject: rand/noise.c (noise_devrandom): Use new Linux system call `getrandom'. X-Git-Tag: 2.2.3~1^2~6 X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/commitdiff_plain/baf5b59c8aad82395688f0a96efcfba4e16b8fc2?hp=ecc296ebb74bb17cfb9998972a4bc28b91e82da0 rand/noise.c (noise_devrandom): Use new Linux system call `getrandom'. The new system call has pretty much the right semantics. If it's available, then try to use it. Annoyingly, the syscall isn't supported in the libc, so we have to do it the hard way. On the plus side, this means that the code will work if built on a system with the syscall defined, and run on one with the right kernel, without introducing a dependency on the libc. If it fails because the kernel entropy pool isn't initialized, then there's no point in messing with the devices because they won't be any better. If it fails because the call isn't there, then it proceeds with other options. --- diff --git a/configure.ac b/configure.ac index 246a74a4..631f7838 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,7 @@ AC_SUBST([limits]) dnl Functions used for noise-gathering. AC_CHECK_FUNCS([setgroups]) +AC_CHECK_HEADERS([linux/random.h]) AC_CACHE_CHECK([whether the freewheel noise generator will work], [catacomb_cv_freewheel], [AC_TRY_LINK( diff --git a/rand/noise.c b/rand/noise.c index 6458f92d..b59fd8ad 100644 --- a/rand/noise.c +++ b/rand/noise.c @@ -29,6 +29,7 @@ #include "config.h" +#include #include #include #include @@ -46,6 +47,11 @@ # include #endif +#if defined(HAVE_LINUX_RANDOM_H) +# include +# include +#endif + #include #include #include @@ -167,6 +173,22 @@ int noise_devrandom(rand_pool *r) struct timeval tv = { 0, 0 }; #endif +#if defined(HAVE_LINUX_RANDOM_H) && \ + defined(GRND_NONBLOCK) && \ + defined(SYS_getrandom) + /* --- Use the new shinies if available --- */ + + while (n < sizeof(buf)) { + if ((len = syscall(SYS_getrandom, buf + n, sizeof(buf) - n, + GRND_NONBLOCK)) <= 0) { + if (errno == ENOSYS) break; + else goto done; + } + n += len; + } + if (n == sizeof(buf)) goto win; +#endif + #ifdef __linux__ /* --- Don't take from `/dev/urandom' if `/dev/random' would block --- */