Skip to content

Commit 61134aa

Browse files
authored
Rollup merge of #78785 - cuviper:weak-getrandom, r=m-ou-se
linux: try to use libc getrandom to allow interposition We'll try to use a weak `getrandom` symbol first, because that allows things like `LD_PRELOAD` interposition. For example, perf measurements might want to disable randomness to get reproducible results. If the weak symbol is not found, we fall back to a raw `SYS_getrandom` call.
2 parents c7e9029 + cd22381 commit 61134aa

File tree

3 files changed

+35
-18
lines changed

3 files changed

+35
-18
lines changed

library/std/src/sys/unix/kernel_copy.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -445,15 +445,15 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
445445
// We store the availability in a global to avoid unnecessary syscalls
446446
static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true);
447447

448-
unsafe fn copy_file_range(
449-
fd_in: libc::c_int,
450-
off_in: *mut libc::loff_t,
451-
fd_out: libc::c_int,
452-
off_out: *mut libc::loff_t,
453-
len: libc::size_t,
454-
flags: libc::c_uint,
455-
) -> libc::c_long {
456-
libc::syscall(libc::SYS_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags)
448+
syscall! {
449+
fn copy_file_range(
450+
fd_in: libc::c_int,
451+
off_in: *mut libc::loff_t,
452+
fd_out: libc::c_int,
453+
off_out: *mut libc::loff_t,
454+
len: libc::size_t,
455+
flags: libc::c_uint
456+
) -> libc::ssize_t
457457
}
458458

459459
let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed);

library/std/src/sys/unix/rand.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,19 @@ mod imp {
2525
use crate::io::Read;
2626

2727
#[cfg(any(target_os = "linux", target_os = "android"))]
28-
fn getrandom(buf: &mut [u8]) -> libc::c_long {
29-
unsafe {
30-
libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr(), buf.len(), libc::GRND_NONBLOCK)
28+
fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
29+
// A weak symbol allows interposition, e.g. for perf measurements that want to
30+
// disable randomness for consistency. Otherwise, we'll try a raw syscall.
31+
// (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28)
32+
syscall! {
33+
fn getrandom(
34+
buffer: *mut libc::c_void,
35+
length: libc::size_t,
36+
flags: libc::c_uint
37+
) -> libc::ssize_t
3138
}
39+
40+
unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
3241
}
3342

3443
#[cfg(not(any(target_os = "linux", target_os = "android")))]

library/std/src/sys/unix/weak.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ unsafe fn fetch(name: &str) -> usize {
6666
libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
6767
}
6868

69-
#[cfg(not(target_os = "linux"))]
69+
#[cfg(not(any(target_os = "linux", target_os = "android")))]
7070
macro_rules! syscall {
7171
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
7272
unsafe fn $name($($arg_name: $t),*) -> $ret {
@@ -84,18 +84,26 @@ macro_rules! syscall {
8484
)
8585
}
8686

87-
#[cfg(target_os = "linux")]
87+
#[cfg(any(target_os = "linux", target_os = "android"))]
8888
macro_rules! syscall {
8989
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
9090
unsafe fn $name($($arg_name:$t),*) -> $ret {
9191
// This looks like a hack, but concat_idents only accepts idents
9292
// (not paths).
9393
use libc::*;
9494

95-
syscall(
96-
concat_idents!(SYS_, $name),
97-
$($arg_name as c_long),*
98-
) as $ret
95+
weak! { fn $name($($t),*) -> $ret }
96+
97+
// Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
98+
// interposition, but if it's not found just use a raw syscall.
99+
if let Some(fun) = $name.get() {
100+
fun($($arg_name),*)
101+
} else {
102+
syscall(
103+
concat_idents!(SYS_, $name),
104+
$($arg_name as c_long),*
105+
) as $ret
106+
}
99107
}
100108
)
101109
}

0 commit comments

Comments
 (0)