about summary refs log tree commit diff
path: root/src/libstd/sys/unix
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-05-06 03:07:00 -0700
committerbors <bors@rust-lang.org>2016-05-06 03:07:00 -0700
commita36c41912ba91435d75ab5702ed8bc30116565fe (patch)
tree21f1a06a4801fefe286ff62d41ffcd27129d5061 /src/libstd/sys/unix
parent6301e22e157ba676b0b2477f6670ab8f954767a8 (diff)
parent61cbd07dec2d9670f170bed44f1815ea29a8a214 (diff)
downloadrust-a36c41912ba91435d75ab5702ed8bc30116565fe.tar.gz
rust-a36c41912ba91435d75ab5702ed8bc30116565fe.zip
Auto merge of #33086 - cardoe:non-blocking-rand-read, r=alexcrichton
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/unix')
-rw-r--r--src/libstd/sys/unix/rand.rs17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index 92c3bf8829a..25a7a3ce50d 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);
                 }