From f875daca54b14d74a3b236b971b88d5e5f739b81 Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Sat, 16 Apr 2016 15:25:56 -0500 Subject: [PATCH] rand: don't block before random pool is initialized If we attempt a read with getrandom() on Linux the syscall can block before the random pool is initialized unless the GRND_NONBLOCK flag is passed. This flag causes getrandom() to instead return EAGAIN while the pool is uninitialized. To avoid downstream users of crate or std functionality that have no ability to avoid this blocking behavior this change causes Rust to read bytes from /dev/urandom while getrandom() would block and once getrandom() is available to use that. Fixes #32953. Signed-off-by: Doug Goldstein --- src/libstd/sys/unix/rand.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 92c3bf8829a..7f52a9c1bee 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -41,8 +41,10 @@ fn getrandom(buf: &mut [u8]) -> libc::c_long { #[cfg(target_arch = "aarch64")] const NR_GETRANDOM: libc::c_long = 278; + const GRND_NONBLOCK: libc::c_uint = 0x0001; + unsafe { - libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0) + libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK) } } @@ -63,6 +65,11 @@ fn getrandom_fill_bytes(v: &mut [u8]) { let err = errno() as libc::c_int; if err == libc::EINTR { continue; + } else if err == libc::EAGAIN { + let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom"); + let mut reader_rng = ReaderRng::new(reader); + reader_rng.fill_bytes(& mut v[read..]); + read += v.len() as usize; } else { panic!("unexpected getrandom error: {}", err); }