Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions library/std/src/sys/pal/unix/stack_overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,15 @@ mod imp {

unsafe {
// this way someone on any unix-y OS can check that all these compile
if cfg!(all(target_os = "linux", not(target_env = "musl"))) {
if cfg!(all(
target_os = "linux",
not(any(target_env = "musl", target_env = "pauthtest"))
)) {
install_main_guard_linux(page_size)
} else if cfg!(all(target_os = "linux", target_env = "musl")) {
} else if cfg!(all(
target_os = "linux",
any(target_env = "musl", target_env = "pauthtest")
)) {
install_main_guard_linux_musl(page_size)
} else if cfg!(target_os = "freebsd") {
#[cfg(not(target_os = "freebsd"))]
Expand Down Expand Up @@ -588,7 +594,10 @@ mod imp {
let mut guardsize = 0;
assert_eq!(libc::pthread_attr_getguardsize(attr.as_ptr(), &mut guardsize), 0);
if guardsize == 0 {
if cfg!(all(target_os = "linux", target_env = "musl")) {
if cfg!(all(
target_os = "linux",
any(target_env = "musl", target_env = "pauthtest")
)) {
// musl versions before 1.1.19 always reported guard
// size obtained from pthread_attr_get_np as zero.
// Use page size as a fallback.
Expand All @@ -604,7 +613,10 @@ mod imp {
let stackaddr = stackptr.addr();
ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) {
Some(stackaddr - guardsize..stackaddr)
} else if cfg!(all(target_os = "linux", target_env = "musl")) {
} else if cfg!(all(
target_os = "linux",
any(target_env = "musl", target_env = "pauthtest")
)) {
Some(stackaddr - guardsize..stackaddr)
} else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))
{
Expand Down
31 changes: 30 additions & 1 deletion library/std/src/sys/personality/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,34 @@ const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
#[cfg(any(target_arch = "loongarch32", target_arch = "loongarch64"))]
const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1

unsafe fn sign_lpad(context: *mut uw::_Unwind_Context, lpad: *const u8) -> *const u8 {
cfg_select! {
all(target_env = "pauthtest", target_arch = "aarch64") => {
// DWARF register number for SP on AArch64.
const SP_REG: i32 = 31;

unsafe {
let sp = uw::_Unwind_GetGR(context, SP_REG) as u64;
let mut addr = lpad as usize;

// `pacib` corresponds to `ptrauth_key_process_dependent_code` in <ptrauth.h>.
core::arch::asm!(
"pacib {addr}, {sp}",
addr = inout(reg) addr,
sp = in(reg) sp,
options(nostack, preserves_flags)
);

lpad.with_addr(addr)
}
}
_ => {
let _ = context;
lpad
}
}
}

// The following code is based on GCC's C and C++ personality routines. For reference, see:
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
Expand Down Expand Up @@ -239,7 +267,8 @@ cfg_select! {
exception_object.cast(),
);
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null());
uw::_Unwind_SetIP(context, lpad);
let maybe_signed_lpad = sign_lpad(context, lpad);
uw::_Unwind_SetIP(context, maybe_signed_lpad);
uw::_URC_INSTALL_CONTEXT
}
EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR,
Expand Down
5 changes: 5 additions & 0 deletions library/std/tests/pipe_subprocess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ fn main() {

fn parent() {
let me = env::current_exe().unwrap();
// If `runner` is set up for current target, we'll be executing `./runner ./test`, not
// just `./test`. For such a case, use the same arguments for child to avoid executing
// `runner` without actual executable.
let args = env::args();

let (rx, tx) = pipe().unwrap();
assert!(
process::Command::new(me)
.args(args)
.env("I_AM_THE_CHILD", "1")
.stdout(tx)
.status()
Expand Down
12 changes: 10 additions & 2 deletions library/std/tests/process_spawning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ fn issue_15149() {
env::join_paths(paths).unwrap()
};

let child_output =
process::Command::new("mytest").env("PATH", &path).arg("child").output().unwrap();
// If `runner` is set up for current target, we'll be executing `./runner ./test`, not
// just `./test`. For such a case, use the same arguments for child to avoid executing
// `runner` without actual executable.
let args = env::args();
let child_output = process::Command::new("mytest")
.args(args)
.env("PATH", &path)
.arg("child")
.output()
.unwrap();

assert!(
child_output.status.success(),
Expand Down
4 changes: 2 additions & 2 deletions library/std_detect/src/detect/os/linux/auxvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub(crate) struct AuxVec {
/// Note that run-time feature detection is not invoked for features that can
/// be detected at compile-time.
///
/// Note: We always directly use `getauxval` on `*-linux-{gnu,musl,ohos}*` and
/// Note: We always directly use `getauxval` on `*-linux-{gnu,musl,ohos,pauthtest}*` and
/// `*-android*` targets rather than `dlsym` it because we can safely assume
/// `getauxval` is linked to the binary.
/// - `*-linux-gnu*` targets ([since Rust 1.64](https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html))
Expand Down Expand Up @@ -125,7 +125,7 @@ fn getauxval(key: usize) -> Result<usize, ()> {
any(
all(
target_os = "linux",
any(target_env = "gnu", target_env = "musl", target_env = "ohos"),
any(target_env = "gnu", target_env = "musl", target_env = "ohos", target_env = "pauthtest"),
),
target_os = "android",
) => {
Expand Down
5 changes: 5 additions & 0 deletions library/unwind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ cfg_select! {
}
}

// For pauthtest the only supported unwinding mechanism is provided by libunwind.
#[cfg(target_env = "pauthtest")]
#[link(name = "unwind")]
unsafe extern "C" {}

// This is the same as musl except that we default to using the system libunwind
// instead of libgcc.
#[cfg(target_env = "ohos")]
Expand Down