Skip to content

Commit

Permalink
Auto merge of rust-lang#33086 - cardoe:non-blocking-rand-read, r=alex…
Browse files Browse the repository at this point in the history
…crichton

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 rust-lang#32953.

Signed-off-by: Doug Goldstein <cardoe@cardoe.com>
  • Loading branch information
bors committed May 6, 2016
2 parents 6301e22 + 61cbd07 commit a36c419
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 3 deletions.
6 changes: 4 additions & 2 deletions src/libstd/collections/hash/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,10 @@ fn test_resize_policy() {
/// The hashes are all keyed by the thread-local random number generator
/// on creation by default. This means that the ordering of the keys is
/// randomized, but makes the tables more resistant to
/// denial-of-service attacks (Hash DoS). This behavior can be
/// overridden with one of the constructors.
/// denial-of-service attacks (Hash DoS). No guarantees are made to the
/// quality of the random data. The implementation uses the best available
/// random data from your platform at the time of creation. This behavior
/// can be overridden with one of the constructors.
///
/// It is required that the keys implement the `Eq` and `Hash` traits, although
/// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`.
Expand Down
17 changes: 16 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,19 @@ mod imp {
let err = errno() as libc::c_int;
if err == libc::EINTR {
continue;
} else if err == libc::EAGAIN {
// if getrandom() returns EAGAIN it would have blocked
// because the non-blocking pool (urandom) has not
// initialized in the kernel yet due to a lack of entropy
// the fallback we do here is to avoid blocking applications
// which could depend on this call without ever knowing
// they do and don't have a work around. The PRNG of
// /dev/urandom will still be used but not over a completely
// full entropy pool
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 a36c419

Please sign in to comment.