1
1
//! Implementations that just need to read from a file
2
- use crate :: {
3
- util_libc:: { open_readonly, sys_fill_exact} ,
4
- Error ,
5
- } ;
2
+ use crate :: Error ;
6
3
use core:: {
7
4
cell:: UnsafeCell ,
8
5
mem:: MaybeUninit ,
9
6
sync:: atomic:: { AtomicUsize , Ordering :: Relaxed } ,
10
7
} ;
11
8
9
+ #[ cfg( not( all( any( target_os = "linux" , target_os = "android" ) , feature = "rustix" ) ) ) ]
10
+ use crate :: util_libc:: { open_readonly, sys_fill_exact} ;
11
+ #[ cfg( all( any( target_os = "linux" , target_os = "android" ) , feature = "rustix" ) ) ]
12
+ use crate :: util_rustix:: { open_readonly, sys_fill_exact} ;
13
+
12
14
/// For all platforms, we use `/dev/urandom` rather than `/dev/random`.
13
15
/// For more information see the linked man pages in lib.rs.
14
16
/// - On Linux, "/dev/urandom is preferred and sufficient in all use cases".
15
17
/// - On Redox, only /dev/urandom is provided.
16
18
/// - On AIX, /dev/urandom will "provide cryptographically secure output".
17
19
/// - On Haiku and QNX Neutrino they are identical.
20
+ #[ cfg( not( feature = "rustix" ) ) ]
18
21
const FILE_PATH : & str = "/dev/urandom\0 " ;
22
+ #[ cfg( feature = "rustix" ) ]
23
+ const FILE_PATH : & str = "/dev/urandom" ;
19
24
const FD_UNINIT : usize = usize:: max_value ( ) ;
20
25
21
26
pub fn getrandom_inner ( dest : & mut [ MaybeUninit < u8 > ] ) -> Result < ( ) , Error > {
22
27
let fd = get_rng_fd ( ) ?;
23
- sys_fill_exact ( dest, |buf| unsafe {
24
- libc:: read ( fd, buf. as_mut_ptr ( ) as * mut libc:: c_void , buf. len ( ) )
25
- } )
28
+ sys_fill_exact ( dest, |buf| read_from_fd ( fd, buf) )
29
+ }
30
+
31
+ #[ cfg( not( feature = "rustix" ) ) ]
32
+ fn read_from_fd ( fd : libc:: c_int , buf : & mut [ MaybeUninit < u8 > ] ) -> libc:: ssize_t {
33
+ unsafe { libc:: read ( fd, buf. as_mut_ptr ( ) as * mut libc:: c_void , buf. len ( ) ) }
34
+ }
35
+
36
+ #[ cfg( feature = "rustix" ) ]
37
+ fn read_from_fd (
38
+ fd : libc:: c_int ,
39
+ buf : & mut [ MaybeUninit < u8 > ] ,
40
+ ) -> Result < ( & mut [ u8 ] , & mut [ MaybeUninit < u8 > ] ) , rustix:: io:: Errno > {
41
+ rustix:: io:: read_uninit ( unsafe { rustix:: fd:: BorrowedFd :: borrow_raw ( fd) } , buf)
26
42
}
27
43
28
44
// Returns the file descriptor for the device file used to retrieve random
@@ -56,7 +72,10 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
56
72
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
57
73
wait_until_rng_ready ( ) ?;
58
74
75
+ #[ allow( unused_unsafe) ]
59
76
let fd = unsafe { open_readonly ( FILE_PATH ) ? } ;
77
+ #[ cfg( feature = "rustix" ) ]
78
+ let fd = rustix:: fd:: IntoRawFd :: into_raw_fd ( fd) ;
60
79
// The fd always fits in a usize without conflicting with FD_UNINIT.
61
80
debug_assert ! ( fd >= 0 && ( fd as usize ) < FD_UNINIT ) ;
62
81
FD . store ( fd as usize , Relaxed ) ;
@@ -65,7 +84,10 @@ fn get_rng_fd() -> Result<libc::c_int, Error> {
65
84
}
66
85
67
86
// Succeeds once /dev/urandom is safe to read from
68
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
87
+ #[ cfg( all(
88
+ any( target_os = "android" , target_os = "linux" ) ,
89
+ not( feature = "rustix" )
90
+ ) ) ]
69
91
fn wait_until_rng_ready ( ) -> Result < ( ) , Error > {
70
92
// Poll /dev/random to make sure it is ok to read from /dev/urandom.
71
93
let fd = unsafe { open_readonly ( "/dev/random\0 " ) ? } ;
@@ -93,6 +115,25 @@ fn wait_until_rng_ready() -> Result<(), Error> {
93
115
}
94
116
}
95
117
118
+ // Succeeds once /dev/urandom is safe to read from
119
+ #[ cfg( all( any( target_os = "android" , target_os = "linux" ) , feature = "rustix" ) ) ]
120
+ fn wait_until_rng_ready ( ) -> Result < ( ) , Error > {
121
+ use rustix:: event;
122
+
123
+ // Open the file.
124
+ let fd = crate :: util_rustix:: open_readonly ( "/dev/random" ) ?;
125
+
126
+ // Poll it until it is ready.
127
+ let mut pfd = [ event:: PollFd :: new ( & fd, event:: PollFlags :: IN ) ] ;
128
+ loop {
129
+ match event:: poll ( & mut pfd, -1 ) {
130
+ Ok ( _) => return Ok ( ( ) ) ,
131
+ Err ( rustix:: io:: Errno :: INTR ) => continue ,
132
+ Err ( err) => return Err ( crate :: util_rustix:: cvt ( err) ) ,
133
+ }
134
+ }
135
+ }
136
+
96
137
struct Mutex ( UnsafeCell < libc:: pthread_mutex_t > ) ;
97
138
98
139
impl Mutex {
0 commit comments