diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index ac2fcfcb53f72..1dc16ef099367 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -445,15 +445,15 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> // We store the availability in a global to avoid unnecessary syscalls static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true); - unsafe fn copy_file_range( - fd_in: libc::c_int, - off_in: *mut libc::loff_t, - fd_out: libc::c_int, - off_out: *mut libc::loff_t, - len: libc::size_t, - flags: libc::c_uint, - ) -> libc::c_long { - libc::syscall(libc::SYS_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags) + syscall! { + fn copy_file_range( + fd_in: libc::c_int, + off_in: *mut libc::loff_t, + fd_out: libc::c_int, + off_out: *mut libc::loff_t, + len: libc::size_t, + flags: libc::c_uint + ) -> libc::ssize_t } let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed); diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs index eed6fbf13b7d2..38ddb41700c4b 100644 --- a/library/std/src/sys/unix/rand.rs +++ b/library/std/src/sys/unix/rand.rs @@ -25,10 +25,19 @@ mod imp { use crate::io::Read; #[cfg(any(target_os = "linux", target_os = "android"))] - fn getrandom(buf: &mut [u8]) -> libc::c_long { - unsafe { - libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr(), buf.len(), libc::GRND_NONBLOCK) + fn getrandom(buf: &mut [u8]) -> libc::ssize_t { + // A weak symbol allows interposition, e.g. for perf measurements that want to + // disable randomness for consistency. Otherwise, we'll try a raw syscall. + // (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28) + syscall! { + fn getrandom( + buffer: *mut libc::c_void, + length: libc::size_t, + flags: libc::c_uint + ) -> libc::ssize_t } + + unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) } } #[cfg(not(any(target_os = "linux", target_os = "android")))] diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index f4b33a00f7c85..6251c3147300a 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -66,7 +66,7 @@ unsafe fn fetch(name: &str) -> usize { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize } -#[cfg(not(target_os = "linux"))] +#[cfg(not(any(target_os = "linux", target_os = "android")))] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name: $t),*) -> $ret { @@ -84,7 +84,7 @@ macro_rules! syscall { ) } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name:$t),*) -> $ret { @@ -92,10 +92,18 @@ macro_rules! syscall { // (not paths). use libc::*; - syscall( - concat_idents!(SYS_, $name), - $($arg_name as c_long),* - ) as $ret + weak! { fn $name($($t),*) -> $ret } + + // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` + // interposition, but if it's not found just use a raw syscall. + if let Some(fun) = $name.get() { + fun($($arg_name),*) + } else { + syscall( + concat_idents!(SYS_, $name), + $($arg_name as c_long),* + ) as $ret + } } ) }