[ruby-core:122562] [Ruby Bug#21448] Random.urandom may fail to fall back to reading /dev/urandom on Linux < 3.17

Issue #21448 has been reported by rhenium (Kazuki Yamaguchi). ---------------------------------------- Bug #21448: Random.urandom may fail to fall back to reading /dev/urandom on Linux < 3.17 https://bugs.ruby-lang.org/issues/21448 * Author: rhenium (Kazuki Yamaguchi) * Status: Open * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- 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 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? -- https://bugs.ruby-lang.org/

Issue #21448 has been updated by nobu (Nobuyoshi Nakada). 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 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 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 ``` ---------------------------------------- Bug #21448: Random.urandom may fail to fall back to reading /dev/urandom on Linux < 3.17 https://bugs.ruby-lang.org/issues/21448#change-113796 * Author: rhenium (Kazuki Yamaguchi) * Status: Open * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED ---------------------------------------- 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 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? -- https://bugs.ruby-lang.org/

Issue #21448 has been updated by rhenium (Kazuki Yamaguchi). 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. ---------------------------------------- Bug #21448: Random.urandom may fail to fall back to reading /dev/urandom on Linux < 3.17 https://bugs.ruby-lang.org/issues/21448#change-113797 * Author: rhenium (Kazuki Yamaguchi) * Status: Open * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED ---------------------------------------- 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 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? -- https://bugs.ruby-lang.org/

Issue #21448 has been updated by nobu (Nobuyoshi Nakada). 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. ---------------------------------------- Bug #21448: Random.urandom may fail to fall back to reading /dev/urandom on Linux < 3.17 https://bugs.ruby-lang.org/issues/21448#change-113812 * Author: rhenium (Kazuki Yamaguchi) * Status: Closed * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED ---------------------------------------- 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 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? -- https://bugs.ruby-lang.org/

Issue #21448 has been updated by k0kubun (Takashi Kokubun). Backport changed from 3.2: REQUIRED, 3.3: REQUIRED, 3.4: REQUIRED to 3.2: REQUIRED, 3.3: REQUIRED, 3.4: DONE ruby_3_4 commit:508daebdcd730e34d5fb750880249deae8025b80 merged revision(s) commit:1181a682a6c314c92686e3701defa1eb44068c4e, commit:d84a811f31a65821642b165d712f380c0cc060e0. ---------------------------------------- Bug #21448: Random.urandom may fail to fall back to reading /dev/urandom on Linux < 3.17 https://bugs.ruby-lang.org/issues/21448#change-114045 * Author: rhenium (Kazuki Yamaguchi) * Status: Closed * Backport: 3.2: REQUIRED, 3.3: REQUIRED, 3.4: DONE ---------------------------------------- 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 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? -- https://bugs.ruby-lang.org/

Issue #21448 has been updated by nagachika (Tomoyuki Chikanaga). Backport changed from 3.2: REQUIRED, 3.3: REQUIRED, 3.4: DONE to 3.2: REQUIRED, 3.3: DONE, 3.4: DONE ruby_3_3 commit:9b9f244b9837d2f3f1128591823eabe55f1a3204 merged revision(s) commit:1181a682a6c314c92686e3701defa1eb44068c4e, commit:0cec4a14fb832aed4b498a21ec0c19765642d408, commit:d84a811f31a65821642b165d712f380c0cc060e0. ---------------------------------------- Bug #21448: Random.urandom may fail to fall back to reading /dev/urandom on Linux < 3.17 https://bugs.ruby-lang.org/issues/21448#change-114111 * Author: rhenium (Kazuki Yamaguchi) * Status: Closed * Backport: 3.2: REQUIRED, 3.3: DONE, 3.4: DONE ---------------------------------------- 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 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? -- https://bugs.ruby-lang.org/
participants (4)
-
k0kubun (Takashi Kokubun)
-
nagachika (Tomoyuki Chikanaga)
-
nobu (Nobuyoshi Nakada)
-
rhenium (Kazuki Yamaguchi)