Skip to content

Commit

Permalink
rand: don't block before random pool is initialized
Browse files Browse the repository at this point in the history
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 <cardoe@cardoe.com>
  • Loading branch information
cardoe committed Apr 19, 2016
1 parent d007824 commit f875dac
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/libstd/sys/unix/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ mod imp {
#[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)
}
}

Expand All @@ -63,6 +65,11 @@ mod imp {
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);
}
Expand Down

0 comments on commit f875dac

Please sign in to comment.