Skip to content

Commit a4b1f2f

Browse files
authored
Linux/Android: Document /dev/random polling considerations. (#452)
See the added comment for details.
1 parent c1e0d31 commit a4b1f2f

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

src/use_file.rs

+28-2
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,36 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
6565
Ok(fd)
6666
}
6767

68-
// Succeeds once /dev/urandom is safe to read from
68+
// Polls /dev/random to make sure it is ok to read from /dev/urandom.
69+
//
70+
// Polling avoids draining the estimated entropy from /dev/random;
71+
// short-lived processes reading even a single byte from /dev/random could
72+
// be problematic if they are being executed faster than entropy is being
73+
// collected.
74+
//
75+
// OTOH, reading a byte instead of polling is more compatible with
76+
// sandboxes that disallow `poll()` but which allow reading /dev/random,
77+
// e.g. sandboxes that assume that `poll()` is for network I/O. This way,
78+
// fewer applications will have to insert pre-sandbox-initialization logic.
79+
// Often (blocking) file I/O is not allowed in such early phases of an
80+
// application for performance and/or security reasons.
81+
//
82+
// It is hard to write a sandbox policy to support `libc::poll()` because
83+
// it may invoke the `poll`, `ppoll`, `ppoll_time64` (since Linux 5.1, with
84+
// newer versions of glibc), and/or (rarely, and probably only on ancient
85+
// systems) `select`. depending on the libc implementation (e.g. glibc vs
86+
// musl), libc version, potentially the kernel version at runtime, and/or
87+
// the target architecture.
88+
//
89+
// BoringSSL and libstd don't try to protect against insecure output from
90+
// `/dev/urandom'; they don't open `/dev/random` at all.
91+
//
92+
// OpenSSL uses `libc::select()` unless the `dev/random` file descriptor
93+
// is too large; if it is too large then it does what we do here.
94+
//
95+
// libsodium uses `libc::poll` similarly to this.
6996
#[cfg(any(target_os = "android", target_os = "linux"))]
7097
fn wait_until_rng_ready() -> Result<(), Error> {
71-
// Poll /dev/random to make sure it is ok to read from /dev/urandom.
7298
let fd = open_readonly(b"/dev/random\0")?;
7399
let mut pfd = libc::pollfd {
74100
fd,

0 commit comments

Comments
 (0)