about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorDoug Goldstein <cardoe@cardoe.com>2016-04-16 15:25:56 -0500
committerDoug Goldstein <cardoe@cardoe.com>2016-04-19 06:24:34 -0500
commitf875daca54b14d74a3b236b971b88d5e5f739b81 (patch)
treeff87be8f91dc18472c64b3757904afe7c8576ede /src/libstd/sys
parentd00782494b47ca7a4ae8e665f99ab10012b45f9c (diff)
downloadrust-f875daca54b14d74a3b236b971b88d5e5f739b81.tar.gz
rust-f875daca54b14d74a3b236b971b88d5e5f739b81.zip
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 <cardoe@cardoe.com>
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/unix/rand.rs9
1 files changed, 8 insertions, 1 deletions
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 @@ 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,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);
                 }