@@ -6,18 +6,68 @@ pub fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
66 sys_fill_exact ( dest, getrandom_syscall)
77}
88
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+
913// 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;
1259
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+ }
2373}
0 commit comments