Skip to content

Commit 4e2528d

Browse files
committed
Move wait_until_rng_ready to linux_android_with_fallback.rs.
It is only used in one configuration, so put it with the other stuff from that configuration.
1 parent 05cdf6f commit 4e2528d

File tree

2 files changed

+64
-57
lines changed

2 files changed

+64
-57
lines changed

src/linux_android_with_fallback.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Implementation for Linux / Android with `/dev/urandom` fallback
22
use crate::{
33
lazy::LazyBool,
4-
util_libc::{getrandom_syscall, last_os_error, sys_fill_exact},
4+
util_libc::{getrandom_syscall, last_os_error, open_readonly, sys_fill_exact},
55
{use_file, Error},
66
};
77
use core::mem::MaybeUninit;
@@ -31,3 +31,65 @@ fn is_getrandom_available() -> bool {
3131
true
3232
}
3333
}
34+
35+
// Polls /dev/random to make sure it is ok to read from /dev/urandom.
36+
//
37+
// Polling avoids draining the estimated entropy from /dev/random;
38+
// short-lived processes reading even a single byte from /dev/random could
39+
// be problematic if they are being executed faster than entropy is being
40+
// collected.
41+
//
42+
// OTOH, reading a byte instead of polling is more compatible with
43+
// sandboxes that disallow `poll()` but which allow reading /dev/random,
44+
// e.g. sandboxes that assume that `poll()` is for network I/O. This way,
45+
// fewer applications will have to insert pre-sandbox-initialization logic.
46+
// Often (blocking) file I/O is not allowed in such early phases of an
47+
// application for performance and/or security reasons.
48+
//
49+
// It is hard to write a sandbox policy to support `libc::poll()` because
50+
// it may invoke the `poll`, `ppoll`, `ppoll_time64` (since Linux 5.1, with
51+
// newer versions of glibc), and/or (rarely, and probably only on ancient
52+
// systems) `select`. depending on the libc implementation (e.g. glibc vs
53+
// musl), libc version, potentially the kernel version at runtime, and/or
54+
// the target architecture.
55+
//
56+
// BoringSSL and libstd don't try to protect against insecure output from
57+
// `/dev/urandom'; they don't open `/dev/random` at all.
58+
//
59+
// OpenSSL uses `libc::select()` unless the `dev/random` file descriptor
60+
// is too large; if it is too large then it does what we do here.
61+
//
62+
// libsodium uses `libc::poll` similarly to this.
63+
pub fn wait_until_rng_ready() -> Result<(), Error> {
64+
let fd = open_readonly(b"/dev/random\0")?;
65+
let mut pfd = libc::pollfd {
66+
fd,
67+
events: libc::POLLIN,
68+
revents: 0,
69+
};
70+
let _guard = DropGuard(|| unsafe {
71+
libc::close(fd);
72+
});
73+
74+
loop {
75+
// A negative timeout means an infinite timeout.
76+
let res = unsafe { libc::poll(&mut pfd, 1, -1) };
77+
if res >= 0 {
78+
debug_assert_eq!(res, 1); // We only used one fd, and cannot timeout.
79+
return Ok(());
80+
}
81+
let err = crate::util_libc::last_os_error();
82+
match err.raw_os_error() {
83+
Some(libc::EINTR) | Some(libc::EAGAIN) => continue,
84+
_ => return Err(err),
85+
}
86+
}
87+
}
88+
89+
struct DropGuard<F: FnMut()>(F);
90+
91+
impl<F: FnMut()> Drop for DropGuard<F> {
92+
fn drop(&mut self) {
93+
self.0()
94+
}
95+
}

src/use_file.rs

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
5656

5757
// On Linux, /dev/urandom might return insecure values.
5858
#[cfg(any(target_os = "android", target_os = "linux"))]
59-
wait_until_rng_ready()?;
59+
crate::imp::wait_until_rng_ready()?;
6060

6161
let fd = open_readonly(FILE_PATH)?;
6262
// The fd always fits in a usize without conflicting with FD_UNINIT.
@@ -74,61 +74,6 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
7474
}
7575
}
7676

77-
// Polls /dev/random to make sure it is ok to read from /dev/urandom.
78-
//
79-
// Polling avoids draining the estimated entropy from /dev/random;
80-
// short-lived processes reading even a single byte from /dev/random could
81-
// be problematic if they are being executed faster than entropy is being
82-
// collected.
83-
//
84-
// OTOH, reading a byte instead of polling is more compatible with
85-
// sandboxes that disallow `poll()` but which allow reading /dev/random,
86-
// e.g. sandboxes that assume that `poll()` is for network I/O. This way,
87-
// fewer applications will have to insert pre-sandbox-initialization logic.
88-
// Often (blocking) file I/O is not allowed in such early phases of an
89-
// application for performance and/or security reasons.
90-
//
91-
// It is hard to write a sandbox policy to support `libc::poll()` because
92-
// it may invoke the `poll`, `ppoll`, `ppoll_time64` (since Linux 5.1, with
93-
// newer versions of glibc), and/or (rarely, and probably only on ancient
94-
// systems) `select`. depending on the libc implementation (e.g. glibc vs
95-
// musl), libc version, potentially the kernel version at runtime, and/or
96-
// the target architecture.
97-
//
98-
// BoringSSL and libstd don't try to protect against insecure output from
99-
// `/dev/urandom'; they don't open `/dev/random` at all.
100-
//
101-
// OpenSSL uses `libc::select()` unless the `dev/random` file descriptor
102-
// is too large; if it is too large then it does what we do here.
103-
//
104-
// libsodium uses `libc::poll` similarly to this.
105-
#[cfg(any(target_os = "android", target_os = "linux"))]
106-
fn wait_until_rng_ready() -> Result<(), Error> {
107-
let fd = open_readonly(b"/dev/random\0")?;
108-
let mut pfd = libc::pollfd {
109-
fd,
110-
events: libc::POLLIN,
111-
revents: 0,
112-
};
113-
let _guard = DropGuard(|| unsafe {
114-
libc::close(fd);
115-
});
116-
117-
loop {
118-
// A negative timeout means an infinite timeout.
119-
let res = unsafe { libc::poll(&mut pfd, 1, -1) };
120-
if res >= 0 {
121-
debug_assert_eq!(res, 1); // We only used one fd, and cannot timeout.
122-
return Ok(());
123-
}
124-
let err = crate::util_libc::last_os_error();
125-
match err.raw_os_error() {
126-
Some(libc::EINTR) | Some(libc::EAGAIN) => continue,
127-
_ => return Err(err),
128-
}
129-
}
130-
}
131-
13277
struct Mutex(UnsafeCell<libc::pthread_mutex_t>);
13378

13479
impl Mutex {

0 commit comments

Comments
 (0)