diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index c20270e830665..3de9276b5acb9 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -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)]`. diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 92c3bf8829adf..25a7a3ce50dc4 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -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) } } @@ -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); }