@@ -6,18 +6,68 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
6
6
sys_fill_exact ( dest, getrandom_syscall)
7
7
}
8
8
9
+ // The value of `EINTR` is not architecture-specific. It is checked against
10
+ // `libc::EINTR` by linux_android_with_fallback.rs.
11
+ pub const EINTR : i32 = 4 ;
12
+
9
13
// Also used by linux_android_with_fallback to check if the syscall is available.
10
- pub fn getrandom_syscall ( buf : & mut [ MaybeUninit < u8 > ] ) -> Result < usize , Error > {
11
- use crate :: util_libc:: last_os_error;
14
+ cfg_if ! {
15
+ // Assume Android always has libc available and always go through libc on
16
+ // Android to support any future possible restrictions on direct syscall
17
+ // access by the Android sandbox.
18
+ //
19
+ // TODO: Expand inilne assembly to other architectures to avoid depending
20
+ // on libc on Linux.
21
+ if #[ cfg( all( target_os = "linux" , target_arch = "x86_64" ) ) ] {
22
+ type Word = u64 ;
23
+ type IWord = i64 ;
24
+
25
+ #[ allow( non_upper_case_globals) ]
26
+ pub const SYS_getrandom : IWord = if cfg!( target_arch = "x86_64" ) { 318 } else { unimplemented!( ) } ;
27
+
28
+ pub fn getrandom_syscall( buf: & mut [ MaybeUninit <u8 >] ) -> Result <usize , Error > {
29
+ const _: ( ) = assert!( core:: mem:: size_of:: <Word >( ) == core:: mem:: size_of:: <usize >( ) ) ;
30
+
31
+ let mut ret: IWord ;
32
+ let flags = 0 ;
33
+ unsafe {
34
+ core:: arch:: asm!(
35
+ "syscall" ,
36
+ in( "rax" ) SYS_getrandom ,
37
+ in( "rdi" ) buf. as_mut_ptr( ) ,
38
+ in( "rsi" ) buf. len( ) ,
39
+ in( "rdx" ) flags,
40
+ lateout( "rcx" ) _,
41
+ lateout( "r11" ) _,
42
+ lateout( "rax" ) ret,
43
+ options( nostack) ,
44
+ ) ;
45
+ }
46
+ match Word :: try_from( ret) {
47
+ Ok ( written) => {
48
+ const _: ( ) = assert!( core:: mem:: size_of:: <Word >( ) <= core:: mem:: size_of:: <usize >( ) ) ;
49
+ Ok ( written as usize )
50
+ } ,
51
+ Err ( _) => {
52
+ Err ( u32 :: try_from( ret. unsigned_abs( ) ) . map_or(
53
+ Error :: UNEXPECTED , Error :: from_os_error) )
54
+ }
55
+ }
56
+ }
57
+ } else {
58
+ use crate :: util_libc:: last_os_error;
12
59
13
- let ret: libc:: c_long = unsafe {
14
- libc:: syscall (
15
- libc:: SYS_getrandom ,
16
- buf. as_mut_ptr ( ) . cast :: < core:: ffi:: c_void > ( ) ,
17
- buf. len ( ) ,
18
- 0 ,
19
- )
20
- } ;
21
- const _: ( ) = assert ! ( core:: mem:: size_of:: <libc:: c_long>( ) == core:: mem:: size_of:: <isize >( ) ) ;
22
- usize:: try_from ( ret as isize ) . map_err ( |_| last_os_error ( ) )
60
+ pub fn getrandom_syscall( buf: & mut [ MaybeUninit <u8 >] ) -> Result <usize , Error > {
61
+ let ret: libc:: c_long = unsafe {
62
+ libc:: syscall(
63
+ libc:: SYS_getrandom ,
64
+ buf. as_mut_ptr( ) . cast:: <core:: ffi:: c_void>( ) ,
65
+ buf. len( ) ,
66
+ 0 ,
67
+ )
68
+ } ;
69
+ const _: ( ) = assert!( core:: mem:: size_of:: <libc:: c_long>( ) == core:: mem:: size_of:: <isize >( ) ) ;
70
+ usize :: try_from( ret as isize ) . map_err( |_| last_os_error( ) )
71
+ }
72
+ }
23
73
}
0 commit comments