@@ -68,30 +68,31 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
68
68
// Succeeds once /dev/urandom is safe to read from
69
69
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
70
70
fn wait_until_rng_ready ( ) -> Result < ( ) , Error > {
71
- // Poll /dev/random to make sure it is ok to read from /dev/urandom.
71
+ // Read a byte from /dev/random to make sure it is ok to read from
72
+ // /dev/urandom. reading a byte instead of polling is more compatible with
73
+ // sandboxes that disallow `poll()` but which allow reading /dev/random,
74
+ // e.g. sandboxes that assume that `poll()` is for network I/O. This way,
75
+ // fewer applications will have to insert pre-sandbox-initialization logic.
76
+ // Often (blocking) file I/O is not allowed in such early phases of an
77
+ // application for performance and/or security reasons. Also it is hard to
78
+ // write a sandbox policy to support `libc::poll()` because it may be
79
+ // invoked as `SYS_POLL`, `SYS_PPOLL`, or even `SYS_SELECT`, depending on
80
+ // the libc implementation (e.g. glibc vs musl), libc version, potentially
81
+ // the kernel version at runtime, and/or the target architecture.
82
+ //
83
+ // BoringSSL and libstd don't try to protect against insecure output from
84
+ // `/dev/urandom'; they don't open `/dev/random` at all.
85
+ //
86
+ // OpenSSL uses `libc::select()` unless the `dev/random` file descriptor
87
+ // is too large; if it is too large then it does what we do here.
72
88
let fd = open_readonly ( b"/dev/random\0 " ) ?;
73
- let mut pfd = libc:: pollfd {
74
- fd,
75
- events : libc:: POLLIN ,
76
- revents : 0 ,
77
- } ;
78
89
let _guard = DropGuard ( || unsafe {
79
90
libc:: close ( fd) ;
80
91
} ) ;
81
-
82
- loop {
83
- // A negative timeout means an infinite timeout.
84
- let res = unsafe { libc:: poll ( & mut pfd, 1 , -1 ) } ;
85
- if res >= 0 {
86
- debug_assert_eq ! ( res, 1 ) ; // We only used one fd, and cannot timeout.
87
- return Ok ( ( ) ) ;
88
- }
89
- let err = crate :: util_libc:: last_os_error ( ) ;
90
- match err. raw_os_error ( ) {
91
- Some ( libc:: EINTR ) | Some ( libc:: EAGAIN ) => continue ,
92
- _ => return Err ( err) ,
93
- }
94
- }
92
+ let mut dummy: [ MaybeUninit < u8 > ; 1 ] = [ MaybeUninit :: uninit ( ) ] ;
93
+ sys_fill_exact ( & mut dummy, |buf| unsafe {
94
+ libc:: read ( fd, buf. as_mut_ptr ( ) . cast :: < c_void > ( ) , buf. len ( ) )
95
+ } )
95
96
}
96
97
97
98
struct Mutex ( UnsafeCell < libc:: pthread_mutex_t > ) ;
0 commit comments