From 5340fb7a494f58d1e67ee1d41341ad19cb7dfce7 Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Wed, 17 Dec 2025 10:05:53 +0000 Subject: [PATCH] Add support for `aarch64-unknown-linux-pauthtest` `aarch64-unknown-linux-pauthtest`, a target that enables Pointer Authentication Code (PAC) support in Rust on AArch64 ELF based Linux systems using a `pauthtest` ABI (provided by LLVM) and pauthtest-enabled sysroot with custom [musl](https://github.com/access-softek/musl), serving as a reference libc implementation. --- Cargo.toml | 1 + build.rs | 22 ++++++++++---- libc-test/build.rs | 8 +++-- src/new/mod.rs | 14 +++++++-- src/unix/linux_like/linux/arch/generic/mod.rs | 24 ++++++++++++--- src/unix/linux_like/linux/mod.rs | 28 ++++++++++++------ src/unix/linux_like/linux_l4re_shared.rs | 29 +++++++++++++++---- src/unix/linux_like/mod.rs | 16 ++++++++-- src/unix/mod.rs | 15 ++++++++-- 9 files changed, 122 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0986492aae876..c07ee8e613359 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,6 +94,7 @@ targets = [ "aarch64-unknown-freebsd", "aarch64-unknown-hermit", "aarch64-unknown-illumos", + "aarch64-unknown-linux-pauthtest", "aarch64-unknown-netbsd", "aarch64-unknown-nto-qnx800", "aarch64-unknown-openbsd", diff --git a/build.rs b/build.rs index b9a8305918518..9e282f5222205 100644 --- a/build.rs +++ b/build.rs @@ -47,7 +47,15 @@ const CHECK_CFG_EXTRA: &[(&str, &[&str])] = &[ ), ( "target_env", - &["illumos", "wasi", "aix", "ohos", "nto71_iosock", "nto80"], + &[ + "illumos", + "wasi", + "aix", + "ohos", + "pauthtest", + "nto71_iosock", + "nto80", + ], ), ( "target_arch", @@ -112,11 +120,15 @@ fn main() { let mut musl_v1_2_3 = env_flag("RUST_LIBC_UNSTABLE_MUSL_V1_2_3"); println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_MUSL_V1_2_3"); - // OpenHarmony uses a fork of the musl libc - let musl = target_env == "musl" || target_env == "ohos"; + // OpenHarmony and pauthtest use a fork of the musl libc + let musl = target_env == "musl" || target_env == "ohos" || target_env == "pauthtest"; - // loongarch64, hexagon, and ohos only exist with recent musl - if target_arch == "loongarch64" || target_arch == "hexagon" || target_env == "ohos" { + // loongarch64, hexagon, ohos and pauthtest only exist with recent musl + if target_arch == "loongarch64" + || target_arch == "hexagon" + || target_env == "ohos" + || target_env == "pauthtest" + { musl_v1_2_3 = true; } diff --git a/libc-test/build.rs b/libc-test/build.rs index 3d5fd89d34478..0c8a0f6fc5cdd 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -3679,7 +3679,7 @@ fn test_linux(target: &str) { // target_env let gnu = target.contains("gnu"); - let musl = target.contains("musl") || target.contains("ohos"); + let musl = target.contains("musl") || target.contains("ohos") || target.contains("pauthtest"); let uclibc = target.contains("uclibc"); match (l4re, gnu, musl, uclibc) { @@ -3716,8 +3716,10 @@ fn test_linux(target: &str) { let mips = target.contains("mips"); let mips64 = target.contains("mips64"); let mips32 = mips && !mips64; + let pauthtest = target.contains("pauthtest"); - let musl_v1_2_3 = env::var("RUST_LIBC_UNSTABLE_MUSL_V1_2_3").is_ok(); + // Force modern musl for pauthtest. + let musl_v1_2_3 = env::var("RUST_LIBC_UNSTABLE_MUSL_V1_2_3").is_ok() || pauthtest; if musl_v1_2_3 { assert!(musl); } @@ -4880,7 +4882,7 @@ fn test_linux(target: &str) { // are included (e.g. because including both sets of headers clashes) fn test_linux_like_apis(target: &str) { let gnu = target.contains("gnu"); - let musl = target.contains("musl") || target.contains("ohos"); + let musl = target.contains("musl") || target.contains("ohos") || target.contains("pauthtest"); let linux = target.contains("linux"); let wali = target.contains("linux") && target.contains("wasm32"); let emscripten = target.contains("emscripten"); diff --git a/src/new/mod.rs b/src/new/mod.rs index 1c5d6a6e17c25..01e31ace66d62 100644 --- a/src/new/mod.rs +++ b/src/new/mod.rs @@ -151,8 +151,12 @@ cfg_if! { ))] { mod glibc; pub(crate) use glibc::*; - } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { - // OhOS also uses the musl libc + } else if #[cfg(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + ))] { + // OhOS and PauthTest also use the musl libc mod musl; pub use musl::sched::*; pub(crate) use musl::*; @@ -218,7 +222,11 @@ cfg_if! { // Per-env headers we export cfg_if! { - if #[cfg(any(target_env = "musl", target_env = "ohos"))] { + if #[cfg(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + ))] { pub use sys::socket::*; } } diff --git a/src/unix/linux_like/linux/arch/generic/mod.rs b/src/unix/linux_like/linux/arch/generic/mod.rs index 37b751715e447..0d54b2377ce22 100644 --- a/src/unix/linux_like/linux/arch/generic/mod.rs +++ b/src/unix/linux_like/linux/arch/generic/mod.rs @@ -53,7 +53,11 @@ cfg_if! { if #[cfg(all( linux_time_bits64, any(target_arch = "arm", target_arch = "x86"), - not(any(target_env = "musl", target_env = "ohos")) + not(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + )) ))] { pub const SO_TIMESTAMP: c_int = SO_TIMESTAMP_NEW; pub const SO_TIMESTAMPNS: c_int = SO_TIMESTAMPNS_NEW; @@ -63,7 +67,11 @@ cfg_if! { } else if #[cfg(all( linux_time_bits64, any(target_arch = "arm", target_arch = "x86"), - any(target_env = "musl", target_env = "ohos") + any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + ) ))] { pub const SO_TIMESTAMP: c_int = 63; pub const SO_TIMESTAMPNS: c_int = 64; @@ -136,7 +144,11 @@ cfg_if! { // of inheriting them from the kernel headers. // For new constants you might need consider updating // musl in the CI as well. - not(any(target_env = "musl", target_env = "ohos")) + not(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + )) ))] { pub const SO_TIMESTAMP_NEW: c_int = 63; pub const SO_TIMESTAMPNS_NEW: c_int = 64; @@ -298,7 +310,11 @@ cfg_if! { #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: crate::__rlimit_resource_t = RLIM_NLIMITS; - } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { + } else if #[cfg(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + ))] { pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs index 6f1261972e9f3..14e55497eeed1 100644 --- a/src/unix/linux_like/linux/mod.rs +++ b/src/unix/linux_like/linux/mod.rs @@ -379,9 +379,9 @@ s! { __pgrp: crate::pid_t, __sd: crate::sigset_t, __ss: crate::sigset_t, - #[cfg(any(target_env = "musl", target_env = "ohos"))] + #[cfg(any(target_env = "musl", target_env = "ohos", target_env = "pauthtest"))] __prio: c_int, - #[cfg(not(any(target_env = "musl", target_env = "ohos")))] + #[cfg(not(any(target_env = "musl", target_env = "ohos", target_env = "pauthtest")))] __sp: crate::sched_param, __policy: c_int, __pad: Padding<[c_int; 16]>, @@ -834,6 +834,7 @@ s! { target_env = "musl", target_env = "ohos", target_env = "uclibc", + target_env = "pauthtest", target_pointer_width = "32" ), repr(align(4)) @@ -843,6 +844,7 @@ s! { not(target_env = "musl"), not(target_env = "ohos"), not(target_env = "uclibc"), + not(target_env = "pauthtest"), target_pointer_width = "64" ), repr(align(8)) @@ -864,7 +866,7 @@ s! { size: [u8; crate::__SIZEOF_PTHREAD_BARRIERATTR_T], } - #[cfg(not(any(target_env = "musl", target_env = "ohos")))] + #[cfg(not(any(target_env = "musl", target_env = "ohos", target_env = "pauthtest")))] #[repr(align(8))] pub struct fanotify_event_metadata { pub event_len: __u32, @@ -1036,28 +1038,28 @@ s! { #[cfg_attr( all( - any(target_env = "musl", target_env = "ohos"), + any(target_env = "musl", target_env = "ohos", target_env = "pauthtest"), target_pointer_width = "32" ), repr(align(4)) )] #[cfg_attr( all( - any(target_env = "musl", target_env = "ohos"), + any(target_env = "musl", target_env = "ohos", target_env = "pauthtest"), target_pointer_width = "64" ), repr(align(8)) )] #[cfg_attr( all( - not(any(target_env = "musl", target_env = "ohos")), + not(any(target_env = "musl", target_env = "ohos", target_env = "pauthtest")), target_arch = "x86" ), repr(align(4)) )] #[cfg_attr( all( - not(any(target_env = "musl", target_env = "ohos")), + not(any(target_env = "musl", target_env = "ohos", target_env = "pauthtest")), not(target_arch = "x86") ), repr(align(8)) @@ -4364,7 +4366,11 @@ extern "C" { // // * musl has 64-bit versions only so aliases the LFS64 symbols to the standard ones cfg_if! { - if #[cfg(not(any(target_env = "musl", target_env = "ohos")))] { + if #[cfg(not(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + )))] { extern "C" { pub fn fallocate64(fd: c_int, mode: c_int, offset: off64_t, len: off64_t) -> c_int; pub fn fgetpos64(stream: *mut crate::FILE, ptr: *mut crate::fpos64_t) -> c_int; @@ -4385,7 +4391,11 @@ cfg_if! { if #[cfg(target_env = "uclibc")] { mod uclibc; pub use self::uclibc::*; - } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { + } else if #[cfg(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + ))] { mod musl; pub use self::musl::*; } else if #[cfg(target_env = "gnu")] { diff --git a/src/unix/linux_like/linux_l4re_shared.rs b/src/unix/linux_like/linux_l4re_shared.rs index cf76b3966ffac..525993856a1d4 100644 --- a/src/unix/linux_like/linux_l4re_shared.rs +++ b/src/unix/linux_like/linux_l4re_shared.rs @@ -444,7 +444,8 @@ cfg_if! { if #[cfg(any( target_env = "gnu", target_env = "musl", - target_env = "ohos" + target_env = "ohos", + target_env = "pauthtest" ))] { pub const CODESET: crate::nl_item = 14; pub const CRNCYSTR: crate::nl_item = 0x4000F; @@ -1502,7 +1503,11 @@ f! { let mut max_addr = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; - if cfg!(any(target_env = "musl", target_env = "ohos")) { + if cfg!(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + )) { // musl and some of its descendants do `>= max_addr` // comparisons in the if statement below. // https://www.openwall.com/lists/musl/2025/12/27/1 @@ -1637,7 +1642,12 @@ safe_f! { cfg_if! { if #[cfg(all( - any(target_env = "gnu", target_env = "musl", target_env = "ohos"), + any( + target_env = "gnu", + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + ), any(target_arch = "x86_64", target_arch = "x86") ))] { extern "C" { @@ -1648,7 +1658,10 @@ cfg_if! { } cfg_if! { - if #[cfg(all(not(target_env = "uclibc"), not(target_env = "ohos")))] { + if #[cfg(all( + not(target_env = "uclibc"), + not(any(target_env = "ohos", target_env = "pauthtest")) + ))] { extern "C" { #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_read64")] pub fn aio_read(aiocbp: *mut crate::aiocb) -> c_int; @@ -1733,7 +1746,7 @@ cfg_if! { extern "C" { #[cfg_attr( - not(any(target_env = "musl", target_env = "ohos")), + not(any(target_env = "musl", target_env = "ohos", target_env = "pauthtest")), link_name = "__xpg_strerror_r" )] pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; @@ -1978,7 +1991,11 @@ extern "C" { } cfg_if! { - if #[cfg(not(any(target_env = "musl", target_env = "ohos")))] { + if #[cfg(not(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + )))] { extern "C" { pub fn freopen64( filename: *const c_char, diff --git a/src/unix/linux_like/mod.rs b/src/unix/linux_like/mod.rs index 2cfa9784a5e84..0661ff9fc535f 100644 --- a/src/unix/linux_like/mod.rs +++ b/src/unix/linux_like/mod.rs @@ -110,7 +110,12 @@ s! { pub tm_zone: *const c_char, } - #[cfg(not(any(target_env = "musl", target_os = "emscripten", target_env = "ohos")))] + #[cfg(not(any( + target_env = "musl", + target_os = "emscripten", + target_env = "ohos", + target_env = "pauthtest" + )))] pub struct sched_param { pub sched_priority: c_int, } @@ -994,7 +999,12 @@ pub const TCP_MD5SIG: c_int = 14; cfg_if! { if #[cfg(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" + ) ))] { // WARN: deprecated pub const TCP_COOKIE_TRANSACTIONS: c_int = 15; @@ -2105,6 +2115,7 @@ cfg_if! { if #[cfg(not(any( target_env = "musl", target_env = "ohos", + target_env = "pauthtest", target_os = "emscripten", )))] { extern "C" { @@ -2170,6 +2181,7 @@ cfg_if! { target_env = "uclibc", target_env = "musl", target_env = "ohos", + target_env = "pauthtest", target_os = "emscripten", )))] { extern "C" { diff --git a/src/unix/mod.rs b/src/unix/mod.rs index ef83c7c9a5532..512e4e41c11a0 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -135,7 +135,12 @@ s! { #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad14: Padding, - #[cfg(any(target_env = "musl", target_env = "ohos", target_os = "emscripten"))] + #[cfg(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest", + target_os = "emscripten" + ))] __reserved: Padding<[c_long; 16]>, } @@ -514,7 +519,11 @@ cfg_if! { #[link(name = "dl", cfg(not(target_feature = "crt-static")))] #[link(name = "c", cfg(not(target_feature = "crt-static")))] extern "C" {} - } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { + } else if #[cfg(any( + target_env = "musl", + target_env = "ohos", + target_env = "pauthtest" + ))] { #[cfg_attr( feature = "rustc-dep-of-std", link( @@ -1444,7 +1453,7 @@ extern "C" { any( all( target_os = "linux", - not(any(target_env = "musl", target_env = "ohos")) + not(any(target_env = "musl", target_env = "ohos", target_env = "pauthtest")) ), target_os = "freebsd", target_os = "cygwin",