Skip to content

Commit e57884b

Browse files
committed
Auto merge of #95824 - zx2c4-forks:grnd_insecure, r=thomcc
Use GRND_INSECURE instead of /dev/urandom when possible From reading the source code, it appears like the desired semantic of std::unix::rand is to always provide some bytes and never block. For that reason GRND_NONBLOCK is checked before calling getrandom(0), so that getrandom(0) won't block. If it would block, then the function falls back to using /dev/urandom, which for the time being doesn't block. There are some drawbacks to using /dev/urandom, however, and so getrandom(GRND_INSECURE) was created as a replacement for this exact circumstance. getrandom(GRND_INSECURE) is the same as /dev/urandom, except: - It won't leave a warning in dmesg if used at early boot time, which is a common occurance (and the reason why I found this issue); - It won't introduce a tiny delay at early boot on newer kernels when /dev/urandom tries to opportunistically create jitter entropy; - It only requires 1 syscall, rather than 3. Other than that, it returns the same "quality" of randomness as /dev/urandom, and never blocks. It's only available on kernels ≥5.6, so we try to use it, cache the result of that attempt, and fall back to to the previous code if it didn't work.
2 parents e6a4afc + 18a9d58 commit e57884b

File tree

3 files changed

+18
-3
lines changed

3 files changed

+18
-3
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -2064,9 +2064,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
20642064

20652065
[[package]]
20662066
name = "libc"
2067-
version = "0.2.125"
2067+
version = "0.2.126"
20682068
source = "registry+https://github.com/rust-lang/crates.io-index"
2069-
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
2069+
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
20702070
dependencies = [
20712071
"rustc-std-workspace-core",
20722072
]

library/std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
1515
panic_unwind = { path = "../panic_unwind", optional = true }
1616
panic_abort = { path = "../panic_abort" }
1717
core = { path = "../core" }
18-
libc = { version = "0.2.125", default-features = false, features = ['rustc-dep-of-std'] }
18+
libc = { version = "0.2.126", default-features = false, features = ['rustc-dep-of-std'] }
1919
compiler_builtins = { version = "0.1.71" }
2020
profiler_builtins = { path = "../profiler_builtins", optional = true }
2121
unwind = { path = "../unwind" }

library/std/src/sys/unix/rand.rs

+15
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ mod imp {
3030

3131
#[cfg(any(target_os = "linux", target_os = "android"))]
3232
fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
33+
use crate::sync::atomic::{AtomicBool, Ordering};
34+
use crate::sys::os::errno;
35+
3336
// A weak symbol allows interposition, e.g. for perf measurements that want to
3437
// disable randomness for consistency. Otherwise, we'll try a raw syscall.
3538
// (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28)
@@ -41,6 +44,18 @@ mod imp {
4144
) -> libc::ssize_t
4245
}
4346

47+
// This provides the best quality random numbers available at the given moment
48+
// without ever blocking, and is preferable to falling back to /dev/urandom.
49+
static GRND_INSECURE_AVAILABLE: AtomicBool = AtomicBool::new(true);
50+
if GRND_INSECURE_AVAILABLE.load(Ordering::Relaxed) {
51+
let ret = unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_INSECURE) };
52+
if ret == -1 && errno() as libc::c_int == libc::EINVAL {
53+
GRND_INSECURE_AVAILABLE.store(false, Ordering::Relaxed);
54+
} else {
55+
return ret;
56+
}
57+
}
58+
4459
unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
4560
}
4661

0 commit comments

Comments
 (0)