summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--random.c26
2 files changed, 27 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index cc9df54c0d..b9fd9ff728 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1826,6 +1826,7 @@ AC_CHECK_FUNCS(getpgid)
AC_CHECK_FUNCS(getpgrp)
AC_CHECK_FUNCS(getpriority)
AC_CHECK_FUNCS(getpwnam_r)
+AC_CHECK_FUNCS(getrandom)
AC_CHECK_FUNCS(getresgid)
AC_CHECK_FUNCS(getresuid)
AC_CHECK_FUNCS(getrlimit)
diff --git a/random.c b/random.c
index 77a8fc7b04..704f78d44d 100644
--- a/random.c
+++ b/random.c
@@ -390,6 +390,32 @@ fill_random_bytes_syscall(void *seed, size_t size, int unused)
CryptGenRandom(prov, size, seed);
return 0;
}
+#elif defined HAVE_GETRANDOM
+#include <sys/random.h>
+
+static int
+fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
+{
+ static rb_atomic_t try_syscall = 1;
+ if (try_syscall) {
+ ssize_t ret;
+ size_t offset = 0;
+ int flags = 0;
+ if (!need_secure)
+ flags = GRND_NONBLOCK;
+ do {
+ errno = 0;
+ ret = getrandom(((char*)seed) + offset, size - offset, flags);
+ if (ret == -1) {
+ ATOMIC_SET(try_syscall, 0);
+ return -1;
+ }
+ offset += (size_t)ret;
+ } while(offset < size);
+ return 0;
+ }
+ return -1;
+}
#elif defined __linux__ && defined __NR_getrandom
#include <linux/random.h>