@@ -6,18 +6,75 @@ 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+ // TODO: Expand inilne assembly to other architectures to avoid depending
16+ // on libc on Linux.
17+ if #[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ] {
18+ type Word = u64 ;
19+ type IWord = i64 ;
20+
21+ // TODO(MSRV(1.78 feature(target_abi))): Enable this and remove `target_pointer_width`
22+ // restriction above.
23+ //
24+ // #[cfg(target_abi = "x32")]
25+ // const __X32_SYSCALL_BIT: Word = 0x40000000;
26+ //
27+ // #[cfg(target_abi = "x832")]
28+ // #[allow(non_upper_case_globals)]
29+ // pub const SYS_getrandom: IWord = 318 | __X32_SYSCALL_BIT;
30+
31+ // #[cfg(not(target_abi = "x832"))]
32+ #[ allow( non_upper_case_globals) ]
33+ pub const SYS_getrandom : IWord = 318 ;
34+
35+ pub fn getrandom_syscall( buf: & mut [ MaybeUninit <u8 >] ) -> Result <usize , Error > {
36+ // Clamp request length to word size; no-op on regular (non-x32) x86_64.
37+ let buflen: Word = Word :: try_from( buf. len( ) ) . unwrap_or( Word :: MAX ) ;
38+ let mut ret: IWord ;
39+ let flags = 0 ;
40+ unsafe {
41+ core:: arch:: asm!(
42+ "syscall" ,
43+ inout( "rax" ) SYS_getrandom => ret,
44+ in( "rdi" ) buf. as_mut_ptr( ) ,
45+ in( "rsi" ) buflen,
46+ in( "rdx" ) flags,
47+ lateout( "rcx" ) _,
48+ lateout( "r11" ) _,
49+ options( nostack) ,
50+ ) ;
51+ }
52+ match Word :: try_from( ret) {
53+ Ok ( written) => {
54+ const _: ( ) = assert!( core:: mem:: size_of:: <Word >( ) <= core:: mem:: size_of:: <usize >( ) ) ;
55+ Ok ( written as usize )
56+ } ,
57+ Err ( _) => {
58+ Err ( u32 :: try_from( ret. unsigned_abs( ) ) . map_or(
59+ Error :: UNEXPECTED , Error :: from_os_error) )
60+ }
61+ }
62+ }
63+ } else {
64+ use crate :: util_libc:: last_os_error;
65+ pub use libc:: SYS_getrandom ;
1266
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 ( ) )
67+ pub fn getrandom_syscall( buf: & mut [ MaybeUninit <u8 >] ) -> Result <usize , Error > {
68+ let ret: libc:: c_long = unsafe {
69+ libc:: syscall(
70+ SYS_getrandom ,
71+ buf. as_mut_ptr( ) . cast:: <core:: ffi:: c_void>( ) ,
72+ buf. len( ) ,
73+ 0 ,
74+ )
75+ } ;
76+ const _: ( ) = assert!( core:: mem:: size_of:: <libc:: c_long>( ) == core:: mem:: size_of:: <isize >( ) ) ;
77+ usize :: try_from( ret as isize ) . map_err( |_| last_os_error( ) )
78+ }
79+ }
2380}
0 commit comments