Project

General

Profile

Actions

Bug #21448

closed

Random.urandom may fail to fall back to reading /dev/urandom on Linux < 3.17

Added by rhenium (Kazuki Yamaguchi) 6 days ago. Updated 3 days ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:122562]

Description

Origianlly reported for tmpdir: https://github.com/ruby/tmpdir/issues/50

On Linux, Random.urandom is expected to first attempt the getrandom(2) syscall (Linux >= 3.17), and fall back to reading from /dev/urandom if it is not supported.

In Ruby 3.1, commit 54c91185c9273b9699693910fa95383c86f2af22 replaced the fallback routine that read from /dev/urandom with a call to getentropy(3), if available at compile time.

On Linux, glibc 2.25 and musl 1.1.20 started to provide a getentropy(3) implementation based on getrandom(2). If Ruby is compiled with such a libc version but run on Linux 3.16 or earlier, both getrandom() and getentropy(3) fail. As a result, Random.urandom becomes unusable, even though /dev/urandom is still available.

I couldn't find the orignal issue the commit was intended to address, except that it appears to related to macOS. Is there a scenario on macOS where CCRandomGenerateBytes() or SecRandomCopyBytes() might fail, while getentropy() will still succeed?

Updated by nobu (Nobuyoshi Nakada) 5 days ago

  • Backport changed from 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED

Unfortunately, despite the same signature, getentropy is different thing in different layers depending on the platform.

  • getentropy(3) - a library function on Linux:

    The getentropy() function is implemented using getrandom(2).

  • getentropy(2) - a system call on macOS:

    Unlike the random(4) pseudo-devices, it is not vulnerable to file descriptor exhaustion attacks and is available when sandboxed or in a chroot, making it more reliable for security-critical applications.

I think we should use getentropy() only on macOS.

It could be solved by either of the following patches.

diff --git i/configure.ac w/configure.ac
index 7270bd5e8b9..144e11fcb57 100644
--- i/configure.ac
+++ w/configure.ac
@@ -2137,3 +2137,3 @@ AC_CHECK_FUNCS(getcwd)
 AC_CHECK_FUNCS(getegid)
-AC_CHECK_FUNCS(getentropy)
+AS_CASE([$target_os], [darwin*], [AC_CHECK_FUNCS(getentropy)])
 AC_CHECK_FUNCS(geteuid)
diff --git i/random.c w/random.c
index f6f63e4cffe..7423f48b1a5 100644
--- i/random.c
+++ w/random.c
@@ -440,3 +440,3 @@ random_init(int argc, VALUE *argv, VALUE obj)
 
-#ifdef HAVE_GETENTROPY
+#if defined(HAVE_GETENTROPY) && defined(__APPLE__)
 # define MAX_SEED_LEN_PER_READ 256

Updated by rhenium (Kazuki Yamaguchi) 5 days ago

FWIW getentropy() has recently made it into POSIX (with a slight difference in errno behavior compared to existing implementations). I think supporting it as an alternative makes sense, not just for macOS.

https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html

My suggestion would be to use getentropy() as an implementation of fill_random_bytes_syscall() rather than replacing fill_random_bytes_urandom().

However, that would mean it is no longer used as a fallback after CCRandomGenerateBytes() or SecRandomCopyBytes() fails on macOS. I'm not sure it can actually happen.

Actions #3

Updated by nobu (Nobuyoshi Nakada) 5 days ago

  • Status changed from Open to Closed

Applied in changeset git|1181a682a6c314c92686e3701defa1eb44068c4e.


[Bug #21448] Use getentropy(2) only on macOS

If this is not a system call, then it is using getrandom (which would
have been tried already), and cannot be used as a replacement for the
random devices.

Updated by nobu (Nobuyoshi Nakada) 3 days ago

rhenium (Kazuki Yamaguchi) wrote in #note-2:

FWIW getentropy() has recently made it into POSIX (with a slight difference in errno behavior compared to existing implementations). I think supporting it as an alternative makes sense, not just for macOS.

https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html

Thank you for the info.

My suggestion would be to use getentropy() as an implementation of fill_random_bytes_syscall() rather than replacing fill_random_bytes_urandom().

However, that would mean it is no longer used as a fallback after CCRandomGenerateBytes() or SecRandomCopyBytes() fails on macOS. I'm not sure it can actually happen.

Reordered and split in to 3 steps.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0