Project

General

Profile

Actions

Bug #11395

closed

ruby gets stuck when entropy_avail is 0

Added by mame (Yusuke Endoh) over 8 years ago. Updated over 8 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 2.3.0dev (2015-07-24 master 51364) [x86_64-linux]
[ruby-core:70114]

Description

When /proc/sys/kernel/random/entropy_avail is 0, Ruby gets stuck during initialization.

$ ruby -v
(stuck)

This is caused by r51182. I think that the GRND_NONBLOCK flag should be set to getrandom syscall.

The following patch works for me. But I have no idea to remove the magic number "1 (= GRND_NONBLOCK)".

diff --git a/random.c b/random.c
index 6452456..9ef89f9 100644
--- a/random.c
+++ b/random.c
@@ -523,11 +523,14 @@ fill_random_bytes_syscall(void *seed, size_t size)
     if (try_syscall) {
 	long ret;
 	errno = 0;
-	ret = syscall(SYS_getrandom, seed, size, 0);
+	ret = syscall(SYS_getrandom, seed, size, 1);
 	if (errno == ENOSYS) {
 	    try_syscall = 0;
 	    return -1;
 	}
+	if (errno == EAGAIN) {
+	    return -1;
+	}
 	if ((size_t)ret == size) return 0;
     }
     return -1;

--
Yusuke Endoh

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Description updated (diff)

including <linux/random.h>?

And checking errno with EAGAIN doesn't seem necessary since the return value should not equal to size.

diff --git i/random.c w/random.c
index 6452456..bea5f85 100644
--- i/random.c
+++ w/random.c
@@ -516,6 +516,8 @@ fill_random_bytes_syscall(void *seed, size_t size)
     return 0;
 }
 #elif defined __linux__ && defined SYS_getrandom
+#include <linux/random.h>
+
 static int
 fill_random_bytes_syscall(void *seed, size_t size)
 {
@@ -523,7 +525,7 @@ fill_random_bytes_syscall(void *seed, size_t size)
     if (try_syscall) {
 	long ret;
 	errno = 0;
-	ret = syscall(SYS_getrandom, seed, size, 0);
+	ret = syscall(SYS_getrandom, seed, size, GRND_NONBLOCK);
 	if (errno == ENOSYS) {
 	    try_syscall = 0;
 	    return -1;

Updated by mame (Yusuke Endoh) over 8 years ago

Well, my system has SYS_getrandom but not GRND_NONBLOCK even in linux/random.h.

I'm using musl libc. It might be a fault of the library.

--
Yusuke Endoh <.

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

Does this header exist?

Updated by mame (Yusuke Endoh) over 8 years ago

Nobuyoshi Nakada wrote:

Does this header exist?

Yes.

compiling random.c
random.c: In function 'fill_random_bytes_syscall':
random.c:528:43: error: 'GRND_NONBLOCK' undeclared (first use in this function)
  ret = syscall(SYS_getrandom, seed, size, GRND_NONBLOCK);
                                           ^
random.c:528:43: note: each undeclared identifier is reported only once for each function it appears in
Makefile:369: recipe for target 'random.o' failed
make: *** [random.o] Error 1
Actions #5

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Status changed from Assigned to Closed

Applied in changeset r51374.


random.c: get rid of blocking

  • random.c (fill_random_bytes_syscall): get rid of blocking when
    no entropy is available. based on the patch by mame in
    [ruby-core:70114]. [Bug #11395]

Updated by mame (Yusuke Endoh) over 8 years ago

Sorry, r51374 may lead to a problem under the following situation.

  • the system uses a new libc that knows SYS_getrandom, but
  • the system uses an old linux kernel that does not know getrandom syscall.

I guess it is not a good idea to determine the availability of getrandom by checking if SYS_getrandom is defined or not.
Instead, it should check the runtime kernel version or something, though it is too ugly.

I bet that we should not use the direct syscall but wait for libc to provide a wrapper function to getrandom.

--
Yusuke Endoh

Updated by mame (Yusuke Endoh) over 8 years ago

Will syscall return ENOSYS if the given syscall number is not available?
If so, I guess the current patch will work well.

--
Yusuke Endoh

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

ENOSYS should be for that purpose.

$ ./x86_64-linux/bin/ruby -v -e 'syscall(9999)'
ruby 2.3.0dev (2015-07-26 trunk 51386) [x86_64-linux]
-e:1: warning: We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.
-e:1:in `syscall': Function not implemented (Errno::ENOSYS)
	from -e:1:in `<main>'
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0