Skip to content

Commit 6d47737

Browse files
committed
Don't leak the file descriptor in rand
1 parent 09a615c commit 6d47737

File tree

1 file changed

+8
-43
lines changed

1 file changed

+8
-43
lines changed

src/libstd/sys/unix/rand.rs

+8-43
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,8 @@ mod imp {
3030
use fs::File;
3131
use io::Read;
3232
use libc;
33-
use sync::atomic::{AtomicBool, AtomicI32, Ordering};
3433
use sys::os::errno;
3534

36-
static GETRANDOM_URANDOM_FD: AtomicI32 = AtomicI32::new(-1);
37-
#[cfg(any(target_os = "linux", target_os = "android"))]
38-
static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
39-
40-
#[cfg(any(target_os = "linux", target_os = "android"))]
41-
fn is_getrandom_permanently_unavailable() -> bool {
42-
GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed)
43-
}
44-
45-
#[cfg(not(any(target_os = "linux", target_os = "android")))]
46-
fn is_getrandom_permanently_unavailable() -> bool {
47-
true
48-
}
49-
5035
#[cfg(any(target_os = "linux", target_os = "android"))]
5136
fn getrandom(buf: &mut [u8]) -> libc::c_long {
5237
unsafe {
@@ -59,7 +44,9 @@ mod imp {
5944

6045
#[cfg(any(target_os = "linux", target_os = "android"))]
6146
fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
62-
if is_getrandom_permanently_unavailable() {
47+
use sync::atomic::{AtomicBool, Ordering};
48+
static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
49+
if GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed) {
6350
return false;
6451
}
6552

@@ -96,33 +83,11 @@ mod imp {
9683
return;
9784
}
9885

99-
// getrandom failed for some reason. If the getrandom call is
100-
// permanently unavailable (OS without getrandom, or OS version without
101-
// getrandom), we'll keep around the fd for /dev/urandom for future
102-
// requests, to avoid re-opening the file on every call.
103-
//
104-
// Otherwise, open /dev/urandom, read from it, and close it again.
105-
use super::super::ext::io::{FromRawFd, IntoRawFd};
106-
let mut fd = GETRANDOM_URANDOM_FD.load(Ordering::Relaxed);
107-
let mut close_fd = false;
108-
if fd == -1 {
109-
if !is_getrandom_permanently_unavailable() {
110-
close_fd = true;
111-
}
112-
let file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
113-
fd = file.into_raw_fd();
114-
// If some other thread also opened /dev/urandom and set the global
115-
// fd already, we close our fd at the end of the function.
116-
if !close_fd && GETRANDOM_URANDOM_FD.compare_and_swap(-1, fd, Ordering::Relaxed) != -1 {
117-
close_fd = true;
118-
}
119-
}
120-
let mut file = unsafe { File::from_raw_fd(fd) };
121-
let res = file.read_exact(v);
122-
if !close_fd {
123-
let _ = file.into_raw_fd();
124-
}
125-
res.expect("failed to read /dev/urandom");
86+
// getrandom failed because it is permanently or temporarily (because
87+
// of missing entropy) unavailable. Open /dev/urandom, read from it,
88+
// and close it again.
89+
let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
90+
file.read_exact(v).expect("failed to read /dev/urandom")
12691
}
12792
}
12893

0 commit comments

Comments
 (0)