diff --git a/src/native/minipal/configure.cmake b/src/native/minipal/configure.cmake index 27c8e803c26f5c..9acaac6ddcc356 100644 --- a/src/native/minipal/configure.cmake +++ b/src/native/minipal/configure.cmake @@ -11,6 +11,7 @@ check_function_exists(sysctlbyname HAVE_SYSCTLBYNAME) check_function_exists(fsync HAVE_FSYNC) check_symbol_exists(arc4random_buf "stdlib.h" HAVE_ARC4RANDOM_BUF) +check_symbol_exists(getrandom "sys/random.h" HAVE_GETRANDOM) check_symbol_exists(O_CLOEXEC fcntl.h HAVE_O_CLOEXEC) check_symbol_exists(CLOCK_MONOTONIC time.h HAVE_CLOCK_MONOTONIC) check_symbol_exists(CLOCK_MONOTONIC_COARSE time.h HAVE_CLOCK_MONOTONIC_COARSE) diff --git a/src/native/minipal/minipalconfig.h.in b/src/native/minipal/minipalconfig.h.in index d9d36129597249..84a619fc8c4096 100644 --- a/src/native/minipal/minipalconfig.h.in +++ b/src/native/minipal/minipalconfig.h.in @@ -2,6 +2,7 @@ #define HAVE_MINIPAL_MINIPALCONFIG_H #cmakedefine01 HAVE_ARC4RANDOM_BUF +#cmakedefine01 HAVE_GETRANDOM #cmakedefine01 HAVE_AUXV_HWCAP_H #cmakedefine01 HAVE_HWPROBE_H #cmakedefine01 HAVE_RESOURCE_H diff --git a/src/native/minipal/random.c b/src/native/minipal/random.c index 4dae7f4d9c487a..1d16b7098478c8 100644 --- a/src/native/minipal/random.c +++ b/src/native/minipal/random.c @@ -16,6 +16,9 @@ #include #include #include +#if HAVE_GETRANDOM +#include +#endif #endif #if defined(__APPLE__) && __APPLE__ #include @@ -100,6 +103,45 @@ int32_t minipal_get_cryptographically_secure_random_bytes(uint8_t* buffer, int32 return BCRYPT_SUCCESS(status) ? 0 : -1; #else +#if HAVE_GETRANDOM + // Try getrandom() first - it's faster than /dev/urandom as it avoids file descriptor overhead. + // getrandom() was added in Linux 3.17 (2014) and glibc 2.25 (2017). + static volatile bool sMissingGetrandom; + + if (!sMissingGetrandom) + { + int32_t offset = 0; + while (offset != bufferLength) + { + ssize_t n = getrandom(buffer + offset, (size_t)(bufferLength - offset), 0); + if (n == -1) + { + if (errno == EINTR) + { + continue; + } + // ENOSYS: syscall not available (old kernel or blocked by seccomp) + // EPERM: operation not permitted (some container environments) + // Fall back to /dev/urandom for these errors + if (errno == ENOSYS || errno == EPERM) + { + sMissingGetrandom = true; + break; + } + return -1; + } + + offset += (int32_t)n; + } + + if (offset == bufferLength) + { + return 0; + } + } +#endif + + // Fallback to /dev/urandom static volatile int rand_des = -1; static bool sMissingDevURandom;