about summary refs log tree commit diff
path: root/src/libstd/sys/unix/rand.rs
diff options
context:
space:
mode:
authorTobias Bucher <tobiasbucher5991@gmail.com>2018-08-29 22:30:29 +0200
committerTobias Bucher <tobiasbucher5991@gmail.com>2018-08-29 22:30:29 +0200
commitd6d280b7df3bc3b333950bc5d0a766d17d433bf9 (patch)
treeebd18208313187515ed961956e62f1efd5a47e1c /src/libstd/sys/unix/rand.rs
parent09a615c09761d5066b19d4b58a6a1d0e515ede45 (diff)
downloadrust-d6d280b7df3bc3b333950bc5d0a766d17d433bf9.tar.gz
rust-d6d280b7df3bc3b333950bc5d0a766d17d433bf9.zip
Don't leak the file descriptor in `rand`
Diffstat (limited to 'src/libstd/sys/unix/rand.rs')
-rw-r--r--src/libstd/sys/unix/rand.rs55
1 files changed, 11 insertions, 44 deletions
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index 857d0370c29..210ace9bbb2 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -29,23 +29,8 @@ pub fn hashmap_random_keys() -> (u64, u64) {
 mod imp {
     use fs::File;
     use io::Read;
-    use libc;
-    use sync::atomic::{AtomicBool, AtomicI32, Ordering};
-    use sys::os::errno;
-
-    static GETRANDOM_URANDOM_FD: AtomicI32 = AtomicI32::new(-1);
-    #[cfg(any(target_os = "linux", target_os = "android"))]
-    static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
-
     #[cfg(any(target_os = "linux", target_os = "android"))]
-    fn is_getrandom_permanently_unavailable() -> bool {
-        GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed)
-    }
-
-    #[cfg(not(any(target_os = "linux", target_os = "android")))]
-    fn is_getrandom_permanently_unavailable() -> bool {
-        true
-    }
+    use libc;
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
     fn getrandom(buf: &mut [u8]) -> libc::c_long {
@@ -59,7 +44,11 @@ mod imp {
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
-        if is_getrandom_permanently_unavailable() {
+        use sync::atomic::{AtomicBool, Ordering};
+        use sys::os::errno;
+
+        static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
+        if GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed) {
             return false;
         }
 
@@ -96,33 +85,11 @@ mod imp {
             return;
         }
 
-        // getrandom failed for some reason. If the getrandom call is
-        // permanently unavailable (OS without getrandom, or OS version without
-        // getrandom), we'll keep around the fd for /dev/urandom for future
-        // requests, to avoid re-opening the file on every call.
-        //
-        // Otherwise, open /dev/urandom, read from it, and close it again.
-        use super::super::ext::io::{FromRawFd, IntoRawFd};
-        let mut fd = GETRANDOM_URANDOM_FD.load(Ordering::Relaxed);
-        let mut close_fd = false;
-        if fd == -1 {
-            if !is_getrandom_permanently_unavailable() {
-                close_fd = true;
-            }
-            let file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
-            fd = file.into_raw_fd();
-            // If some other thread also opened /dev/urandom and set the global
-            // fd already, we close our fd at the end of the function.
-            if !close_fd && GETRANDOM_URANDOM_FD.compare_and_swap(-1, fd, Ordering::Relaxed) != -1 {
-                close_fd = true;
-            }
-        }
-        let mut file = unsafe { File::from_raw_fd(fd) };
-        let res = file.read_exact(v);
-        if !close_fd {
-            let _ = file.into_raw_fd();
-        }
-        res.expect("failed to read /dev/urandom");
+        // getrandom failed because it is permanently or temporarily (because
+        // of missing entropy) unavailable. Open /dev/urandom, read from it,
+        // and close it again.
+        let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
+        file.read_exact(v).expect("failed to read /dev/urandom")
     }
 }