summaryrefslogtreecommitdiff
path: root/random.c
diff options
context:
space:
mode:
authorglass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-02-10 08:21:33 +0000
committerglass <glass@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-02-10 08:21:33 +0000
commit1a8583de72e12e139e9c7fbcfc026c2cbf410519 (patch)
treea1f5bedcb9eb706643e71cd49b092bdbb68a9f22 /random.c
parentb1cb15c4a42575eb8ceb1c89256f37c662e20172 (diff)
random.c: use getrandom() if available.
getrandom() is supported by glibc 2.25 or later. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67043 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'random.c')
-rw-r--r--random.c26
1 files changed, 26 insertions, 0 deletions
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>