1b8a62b91Sopenharmony_ci//! Bindings for the Linux `prctl` system call. 2b8a62b91Sopenharmony_ci//! 3b8a62b91Sopenharmony_ci//! There are similarities (but also differences) with FreeBSD's `procctl` system call, whose 4b8a62b91Sopenharmony_ci//! interface is located in the `procctl.rs` file. 5b8a62b91Sopenharmony_ci 6b8a62b91Sopenharmony_ci#![allow(unsafe_code)] 7b8a62b91Sopenharmony_ci 8b8a62b91Sopenharmony_ciuse core::convert::{TryFrom, TryInto}; 9b8a62b91Sopenharmony_ciuse core::mem::MaybeUninit; 10b8a62b91Sopenharmony_ciuse core::ptr::NonNull; 11b8a62b91Sopenharmony_ciuse core::{mem, ptr}; 12b8a62b91Sopenharmony_ci 13b8a62b91Sopenharmony_ciuse bitflags::bitflags; 14b8a62b91Sopenharmony_ci 15b8a62b91Sopenharmony_ciuse crate::backend::c::{c_int, c_uint, c_void}; 16b8a62b91Sopenharmony_ciuse crate::backend::process::syscalls; 17b8a62b91Sopenharmony_ciuse crate::backend::process::types::Signal; 18b8a62b91Sopenharmony_ciuse crate::fd::{AsRawFd, BorrowedFd}; 19b8a62b91Sopenharmony_ciuse crate::ffi::CStr; 20b8a62b91Sopenharmony_ciuse crate::io; 21b8a62b91Sopenharmony_ciuse crate::process::{Pid, RawPid}; 22b8a62b91Sopenharmony_ci 23b8a62b91Sopenharmony_ci// 24b8a62b91Sopenharmony_ci// Helper functions. 25b8a62b91Sopenharmony_ci// 26b8a62b91Sopenharmony_ci 27b8a62b91Sopenharmony_ci#[inline] 28b8a62b91Sopenharmony_cipub(crate) unsafe fn prctl_1arg(option: c_int) -> io::Result<c_int> { 29b8a62b91Sopenharmony_ci const NULL: *mut c_void = ptr::null_mut(); 30b8a62b91Sopenharmony_ci syscalls::prctl(option, NULL, NULL, NULL, NULL) 31b8a62b91Sopenharmony_ci} 32b8a62b91Sopenharmony_ci 33b8a62b91Sopenharmony_ci#[inline] 34b8a62b91Sopenharmony_cipub(crate) unsafe fn prctl_2args(option: c_int, arg2: *mut c_void) -> io::Result<c_int> { 35b8a62b91Sopenharmony_ci const NULL: *mut c_void = ptr::null_mut(); 36b8a62b91Sopenharmony_ci syscalls::prctl(option, arg2, NULL, NULL, NULL) 37b8a62b91Sopenharmony_ci} 38b8a62b91Sopenharmony_ci 39b8a62b91Sopenharmony_ci#[inline] 40b8a62b91Sopenharmony_cipub(crate) unsafe fn prctl_3args( 41b8a62b91Sopenharmony_ci option: c_int, 42b8a62b91Sopenharmony_ci arg2: *mut c_void, 43b8a62b91Sopenharmony_ci arg3: *mut c_void, 44b8a62b91Sopenharmony_ci) -> io::Result<c_int> { 45b8a62b91Sopenharmony_ci syscalls::prctl(option, arg2, arg3, ptr::null_mut(), ptr::null_mut()) 46b8a62b91Sopenharmony_ci} 47b8a62b91Sopenharmony_ci 48b8a62b91Sopenharmony_ci#[inline] 49b8a62b91Sopenharmony_cipub(crate) unsafe fn prctl_get_at_arg2_optional<P>(option: i32) -> io::Result<P> { 50b8a62b91Sopenharmony_ci let mut value: MaybeUninit<P> = MaybeUninit::uninit(); 51b8a62b91Sopenharmony_ci prctl_2args(option, value.as_mut_ptr().cast())?; 52b8a62b91Sopenharmony_ci Ok(value.assume_init()) 53b8a62b91Sopenharmony_ci} 54b8a62b91Sopenharmony_ci 55b8a62b91Sopenharmony_ci#[inline] 56b8a62b91Sopenharmony_cipub(crate) unsafe fn prctl_get_at_arg2<P, T>(option: i32) -> io::Result<T> 57b8a62b91Sopenharmony_ciwhere 58b8a62b91Sopenharmony_ci P: Default, 59b8a62b91Sopenharmony_ci T: TryFrom<P, Error = io::Errno>, 60b8a62b91Sopenharmony_ci{ 61b8a62b91Sopenharmony_ci let mut value: P = Default::default(); 62b8a62b91Sopenharmony_ci prctl_2args(option, ((&mut value) as *mut P).cast())?; 63b8a62b91Sopenharmony_ci TryFrom::try_from(value) 64b8a62b91Sopenharmony_ci} 65b8a62b91Sopenharmony_ci 66b8a62b91Sopenharmony_ci// 67b8a62b91Sopenharmony_ci// PR_GET_PDEATHSIG/PR_SET_PDEATHSIG 68b8a62b91Sopenharmony_ci// 69b8a62b91Sopenharmony_ci 70b8a62b91Sopenharmony_ciconst PR_GET_PDEATHSIG: c_int = 2; 71b8a62b91Sopenharmony_ci 72b8a62b91Sopenharmony_ci/// Get the current value of the parent process death signal. 73b8a62b91Sopenharmony_ci/// 74b8a62b91Sopenharmony_ci/// # References 75b8a62b91Sopenharmony_ci/// - [Linux: `prctl(PR_GET_PDEATHSIG,...)`] 76b8a62b91Sopenharmony_ci/// - [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`] 77b8a62b91Sopenharmony_ci/// 78b8a62b91Sopenharmony_ci/// [Linux: `prctl(PR_GET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 79b8a62b91Sopenharmony_ci/// [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 80b8a62b91Sopenharmony_ci#[inline] 81b8a62b91Sopenharmony_cipub fn parent_process_death_signal() -> io::Result<Option<Signal>> { 82b8a62b91Sopenharmony_ci unsafe { prctl_get_at_arg2_optional::<c_int>(PR_GET_PDEATHSIG) }.map(Signal::from_raw) 83b8a62b91Sopenharmony_ci} 84b8a62b91Sopenharmony_ci 85b8a62b91Sopenharmony_ciconst PR_SET_PDEATHSIG: c_int = 1; 86b8a62b91Sopenharmony_ci 87b8a62b91Sopenharmony_ci/// Set the parent-death signal of the calling process. 88b8a62b91Sopenharmony_ci/// 89b8a62b91Sopenharmony_ci/// # References 90b8a62b91Sopenharmony_ci/// - [Linux: `prctl(PR_SET_PDEATHSIG,...)`] 91b8a62b91Sopenharmony_ci/// - [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`] 92b8a62b91Sopenharmony_ci/// 93b8a62b91Sopenharmony_ci/// [Linux: `prctl(PR_SET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 94b8a62b91Sopenharmony_ci/// [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 95b8a62b91Sopenharmony_ci#[inline] 96b8a62b91Sopenharmony_cipub fn set_parent_process_death_signal(signal: Option<Signal>) -> io::Result<()> { 97b8a62b91Sopenharmony_ci let signal = signal.map_or(0_usize, |signal| signal as usize); 98b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_PDEATHSIG, signal as *mut _) }.map(|_r| ()) 99b8a62b91Sopenharmony_ci} 100b8a62b91Sopenharmony_ci 101b8a62b91Sopenharmony_ci// 102b8a62b91Sopenharmony_ci// PR_GET_DUMPABLE/PR_SET_DUMPABLE 103b8a62b91Sopenharmony_ci// 104b8a62b91Sopenharmony_ci 105b8a62b91Sopenharmony_ciconst PR_GET_DUMPABLE: c_int = 3; 106b8a62b91Sopenharmony_ci 107b8a62b91Sopenharmony_ciconst SUID_DUMP_DISABLE: i32 = 0; 108b8a62b91Sopenharmony_ciconst SUID_DUMP_USER: i32 = 1; 109b8a62b91Sopenharmony_ciconst SUID_DUMP_ROOT: i32 = 2; 110b8a62b91Sopenharmony_ci 111b8a62b91Sopenharmony_ci/// `SUID_DUMP_*`. 112b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 113b8a62b91Sopenharmony_ci#[repr(i32)] 114b8a62b91Sopenharmony_cipub enum DumpableBehavior { 115b8a62b91Sopenharmony_ci /// Not dumpable. 116b8a62b91Sopenharmony_ci NotDumpable = SUID_DUMP_DISABLE, 117b8a62b91Sopenharmony_ci /// Dumpable. 118b8a62b91Sopenharmony_ci Dumpable = SUID_DUMP_USER, 119b8a62b91Sopenharmony_ci /// Dumpable but only readable by root. 120b8a62b91Sopenharmony_ci DumpableReadableOnlyByRoot = SUID_DUMP_ROOT, 121b8a62b91Sopenharmony_ci} 122b8a62b91Sopenharmony_ci 123b8a62b91Sopenharmony_ciimpl TryFrom<i32> for DumpableBehavior { 124b8a62b91Sopenharmony_ci type Error = io::Errno; 125b8a62b91Sopenharmony_ci 126b8a62b91Sopenharmony_ci fn try_from(value: i32) -> Result<Self, Self::Error> { 127b8a62b91Sopenharmony_ci match value { 128b8a62b91Sopenharmony_ci SUID_DUMP_DISABLE => Ok(Self::NotDumpable), 129b8a62b91Sopenharmony_ci SUID_DUMP_USER => Ok(Self::Dumpable), 130b8a62b91Sopenharmony_ci SUID_DUMP_ROOT => Ok(Self::DumpableReadableOnlyByRoot), 131b8a62b91Sopenharmony_ci _ => Err(io::Errno::RANGE), 132b8a62b91Sopenharmony_ci } 133b8a62b91Sopenharmony_ci } 134b8a62b91Sopenharmony_ci} 135b8a62b91Sopenharmony_ci 136b8a62b91Sopenharmony_ci/// Get the current state of the calling process's `dumpable` attribute. 137b8a62b91Sopenharmony_ci/// 138b8a62b91Sopenharmony_ci/// # References 139b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_DUMPABLE,...)`] 140b8a62b91Sopenharmony_ci/// 141b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_DUMPABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 142b8a62b91Sopenharmony_ci#[inline] 143b8a62b91Sopenharmony_cipub fn dumpable_behavior() -> io::Result<DumpableBehavior> { 144b8a62b91Sopenharmony_ci unsafe { prctl_1arg(PR_GET_DUMPABLE) }.and_then(TryInto::try_into) 145b8a62b91Sopenharmony_ci} 146b8a62b91Sopenharmony_ci 147b8a62b91Sopenharmony_ciconst PR_SET_DUMPABLE: c_int = 4; 148b8a62b91Sopenharmony_ci 149b8a62b91Sopenharmony_ci/// Set the state of the `dumpable` attribute, which determines whether the process can be traced 150b8a62b91Sopenharmony_ci/// and whether core dumps are produced for the calling process upon delivery of a signal whose 151b8a62b91Sopenharmony_ci/// default behavior is to produce a core dump. 152b8a62b91Sopenharmony_ci/// 153b8a62b91Sopenharmony_ci/// A similar function with the same name is available on FreeBSD (as part of the `procctl` 154b8a62b91Sopenharmony_ci/// interface), but it has an extra argument which allows to select a process other then the 155b8a62b91Sopenharmony_ci/// current process. 156b8a62b91Sopenharmony_ci/// 157b8a62b91Sopenharmony_ci/// # References 158b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_DUMPABLE,...)`] 159b8a62b91Sopenharmony_ci/// 160b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_DUMPABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 161b8a62b91Sopenharmony_ci#[inline] 162b8a62b91Sopenharmony_cipub fn set_dumpable_behavior(config: DumpableBehavior) -> io::Result<()> { 163b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_DUMPABLE, config as usize as *mut _) }.map(|_r| ()) 164b8a62b91Sopenharmony_ci} 165b8a62b91Sopenharmony_ci 166b8a62b91Sopenharmony_ci// 167b8a62b91Sopenharmony_ci// PR_GET_UNALIGN/PR_SET_UNALIGN 168b8a62b91Sopenharmony_ci// 169b8a62b91Sopenharmony_ci 170b8a62b91Sopenharmony_ciconst PR_GET_UNALIGN: c_int = 5; 171b8a62b91Sopenharmony_ci 172b8a62b91Sopenharmony_cibitflags! { 173b8a62b91Sopenharmony_ci /// `PR_UNALIGN_*`. 174b8a62b91Sopenharmony_ci pub struct UnalignedAccessControl: u32 { 175b8a62b91Sopenharmony_ci /// Silently fix up unaligned user accesses. 176b8a62b91Sopenharmony_ci const NO_PRINT = 1; 177b8a62b91Sopenharmony_ci /// Generate `SIGBUS` on unaligned user access. 178b8a62b91Sopenharmony_ci const SIGBUS = 2; 179b8a62b91Sopenharmony_ci } 180b8a62b91Sopenharmony_ci} 181b8a62b91Sopenharmony_ci 182b8a62b91Sopenharmony_ci/// Get unaligned access control bits. 183b8a62b91Sopenharmony_ci/// 184b8a62b91Sopenharmony_ci/// # References 185b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_UNALIGN,...)`] 186b8a62b91Sopenharmony_ci/// 187b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_UNALIGN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 188b8a62b91Sopenharmony_ci#[inline] 189b8a62b91Sopenharmony_cipub fn unaligned_access_control() -> io::Result<UnalignedAccessControl> { 190b8a62b91Sopenharmony_ci let r = unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_UNALIGN)? }; 191b8a62b91Sopenharmony_ci UnalignedAccessControl::from_bits(r).ok_or(io::Errno::RANGE) 192b8a62b91Sopenharmony_ci} 193b8a62b91Sopenharmony_ci 194b8a62b91Sopenharmony_ciconst PR_SET_UNALIGN: c_int = 6; 195b8a62b91Sopenharmony_ci 196b8a62b91Sopenharmony_ci/// Set unaligned access control bits. 197b8a62b91Sopenharmony_ci/// 198b8a62b91Sopenharmony_ci/// # References 199b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_UNALIGN,...)`] 200b8a62b91Sopenharmony_ci/// 201b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_UNALIGN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 202b8a62b91Sopenharmony_ci#[inline] 203b8a62b91Sopenharmony_cipub fn set_unaligned_access_control(config: UnalignedAccessControl) -> io::Result<()> { 204b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_UNALIGN, config.bits() as usize as *mut _) }.map(|_r| ()) 205b8a62b91Sopenharmony_ci} 206b8a62b91Sopenharmony_ci 207b8a62b91Sopenharmony_ci// 208b8a62b91Sopenharmony_ci// PR_GET_FPEMU/PR_SET_FPEMU 209b8a62b91Sopenharmony_ci// 210b8a62b91Sopenharmony_ci 211b8a62b91Sopenharmony_ciconst PR_GET_FPEMU: c_int = 9; 212b8a62b91Sopenharmony_ci 213b8a62b91Sopenharmony_cibitflags! { 214b8a62b91Sopenharmony_ci /// `PR_FPEMU_*`. 215b8a62b91Sopenharmony_ci pub struct FloatingPointEmulationControl: u32 { 216b8a62b91Sopenharmony_ci /// Silently emulate floating point operations accesses. 217b8a62b91Sopenharmony_ci const NO_PRINT = 1; 218b8a62b91Sopenharmony_ci /// Don't emulate floating point operations, send `SIGFPE` instead. 219b8a62b91Sopenharmony_ci const SIGFPE = 2; 220b8a62b91Sopenharmony_ci } 221b8a62b91Sopenharmony_ci} 222b8a62b91Sopenharmony_ci 223b8a62b91Sopenharmony_ci/// Get floating point emulation control bits. 224b8a62b91Sopenharmony_ci/// 225b8a62b91Sopenharmony_ci/// # References 226b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_FPEMU,...)`] 227b8a62b91Sopenharmony_ci/// 228b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_FPEMU,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 229b8a62b91Sopenharmony_ci#[inline] 230b8a62b91Sopenharmony_cipub fn floating_point_emulation_control() -> io::Result<FloatingPointEmulationControl> { 231b8a62b91Sopenharmony_ci let r = unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_FPEMU)? }; 232b8a62b91Sopenharmony_ci FloatingPointEmulationControl::from_bits(r).ok_or(io::Errno::RANGE) 233b8a62b91Sopenharmony_ci} 234b8a62b91Sopenharmony_ci 235b8a62b91Sopenharmony_ciconst PR_SET_FPEMU: c_int = 10; 236b8a62b91Sopenharmony_ci 237b8a62b91Sopenharmony_ci/// Set floating point emulation control bits. 238b8a62b91Sopenharmony_ci/// 239b8a62b91Sopenharmony_ci/// # References 240b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_FPEMU,...)`] 241b8a62b91Sopenharmony_ci/// 242b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_FPEMU,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 243b8a62b91Sopenharmony_ci#[inline] 244b8a62b91Sopenharmony_cipub fn set_floating_point_emulation_control( 245b8a62b91Sopenharmony_ci config: FloatingPointEmulationControl, 246b8a62b91Sopenharmony_ci) -> io::Result<()> { 247b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_FPEMU, config.bits() as usize as *mut _) }.map(|_r| ()) 248b8a62b91Sopenharmony_ci} 249b8a62b91Sopenharmony_ci 250b8a62b91Sopenharmony_ci// 251b8a62b91Sopenharmony_ci// PR_GET_FPEXC/PR_SET_FPEXC 252b8a62b91Sopenharmony_ci// 253b8a62b91Sopenharmony_ci 254b8a62b91Sopenharmony_ciconst PR_GET_FPEXC: c_int = 11; 255b8a62b91Sopenharmony_ci 256b8a62b91Sopenharmony_cibitflags! { 257b8a62b91Sopenharmony_ci /// Zero means floating point exceptions are disabled. 258b8a62b91Sopenharmony_ci pub struct FloatingPointExceptionMode: u32 { 259b8a62b91Sopenharmony_ci /// Async non-recoverable exception mode. 260b8a62b91Sopenharmony_ci const NONRECOV = 1; 261b8a62b91Sopenharmony_ci /// Async recoverable exception mode. 262b8a62b91Sopenharmony_ci const ASYNC = 2; 263b8a62b91Sopenharmony_ci /// Precise exception mode. 264b8a62b91Sopenharmony_ci const PRECISE = 3; 265b8a62b91Sopenharmony_ci 266b8a62b91Sopenharmony_ci /// Use FPEXC for floating point exception enables. 267b8a62b91Sopenharmony_ci const SW_ENABLE = 0x80; 268b8a62b91Sopenharmony_ci /// Floating point divide by zero. 269b8a62b91Sopenharmony_ci const DIV = 0x01_0000; 270b8a62b91Sopenharmony_ci /// Floating point overflow. 271b8a62b91Sopenharmony_ci const OVF = 0x02_0000; 272b8a62b91Sopenharmony_ci /// Floating point underflow. 273b8a62b91Sopenharmony_ci const UND = 0x04_0000; 274b8a62b91Sopenharmony_ci /// Floating point inexact result. 275b8a62b91Sopenharmony_ci const RES = 0x08_0000; 276b8a62b91Sopenharmony_ci /// Floating point invalid operation. 277b8a62b91Sopenharmony_ci const INV = 0x10_0000; 278b8a62b91Sopenharmony_ci } 279b8a62b91Sopenharmony_ci} 280b8a62b91Sopenharmony_ci 281b8a62b91Sopenharmony_ci/// Get floating point exception mode. 282b8a62b91Sopenharmony_ci/// 283b8a62b91Sopenharmony_ci/// # References 284b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_FPEXC,...)`] 285b8a62b91Sopenharmony_ci/// 286b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_FPEXC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 287b8a62b91Sopenharmony_ci#[inline] 288b8a62b91Sopenharmony_cipub fn floating_point_exception_mode() -> io::Result<Option<FloatingPointExceptionMode>> { 289b8a62b91Sopenharmony_ci unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_FPEXC) } 290b8a62b91Sopenharmony_ci .map(FloatingPointExceptionMode::from_bits) 291b8a62b91Sopenharmony_ci} 292b8a62b91Sopenharmony_ci 293b8a62b91Sopenharmony_ciconst PR_SET_FPEXC: c_int = 12; 294b8a62b91Sopenharmony_ci 295b8a62b91Sopenharmony_ci/// Set floating point exception mode. 296b8a62b91Sopenharmony_ci/// 297b8a62b91Sopenharmony_ci/// # References 298b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_FPEXC,...)`] 299b8a62b91Sopenharmony_ci/// 300b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_FPEXC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 301b8a62b91Sopenharmony_ci#[inline] 302b8a62b91Sopenharmony_cipub fn set_floating_point_exception_mode( 303b8a62b91Sopenharmony_ci config: Option<FloatingPointExceptionMode>, 304b8a62b91Sopenharmony_ci) -> io::Result<()> { 305b8a62b91Sopenharmony_ci let config = config.as_ref().map_or(0, FloatingPointExceptionMode::bits); 306b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_FPEXC, config as usize as *mut _) }.map(|_r| ()) 307b8a62b91Sopenharmony_ci} 308b8a62b91Sopenharmony_ci 309b8a62b91Sopenharmony_ci// 310b8a62b91Sopenharmony_ci// PR_GET_TIMING/PR_SET_TIMING 311b8a62b91Sopenharmony_ci// 312b8a62b91Sopenharmony_ci 313b8a62b91Sopenharmony_ciconst PR_GET_TIMING: c_int = 13; 314b8a62b91Sopenharmony_ci 315b8a62b91Sopenharmony_ciconst PR_TIMING_STATISTICAL: i32 = 0; 316b8a62b91Sopenharmony_ciconst PR_TIMING_TIMESTAMP: i32 = 1; 317b8a62b91Sopenharmony_ci 318b8a62b91Sopenharmony_ci/// `PR_TIMING_*`. 319b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 320b8a62b91Sopenharmony_ci#[repr(i32)] 321b8a62b91Sopenharmony_cipub enum TimingMethod { 322b8a62b91Sopenharmony_ci /// Normal, traditional, statistical process timing. 323b8a62b91Sopenharmony_ci Statistical = PR_TIMING_STATISTICAL, 324b8a62b91Sopenharmony_ci /// Accurate timestamp based process timing. 325b8a62b91Sopenharmony_ci TimeStamp = PR_TIMING_TIMESTAMP, 326b8a62b91Sopenharmony_ci} 327b8a62b91Sopenharmony_ci 328b8a62b91Sopenharmony_ciimpl TryFrom<i32> for TimingMethod { 329b8a62b91Sopenharmony_ci type Error = io::Errno; 330b8a62b91Sopenharmony_ci 331b8a62b91Sopenharmony_ci fn try_from(value: i32) -> Result<Self, Self::Error> { 332b8a62b91Sopenharmony_ci match value { 333b8a62b91Sopenharmony_ci PR_TIMING_STATISTICAL => Ok(Self::Statistical), 334b8a62b91Sopenharmony_ci PR_TIMING_TIMESTAMP => Ok(Self::TimeStamp), 335b8a62b91Sopenharmony_ci _ => Err(io::Errno::RANGE), 336b8a62b91Sopenharmony_ci } 337b8a62b91Sopenharmony_ci } 338b8a62b91Sopenharmony_ci} 339b8a62b91Sopenharmony_ci 340b8a62b91Sopenharmony_ci/// Get which process timing method is currently in use. 341b8a62b91Sopenharmony_ci/// 342b8a62b91Sopenharmony_ci/// # References 343b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_TIMING,...)`] 344b8a62b91Sopenharmony_ci/// 345b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_TIMING,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 346b8a62b91Sopenharmony_ci#[inline] 347b8a62b91Sopenharmony_cipub fn timing_method() -> io::Result<TimingMethod> { 348b8a62b91Sopenharmony_ci unsafe { prctl_1arg(PR_GET_TIMING) }.and_then(TryInto::try_into) 349b8a62b91Sopenharmony_ci} 350b8a62b91Sopenharmony_ci 351b8a62b91Sopenharmony_ciconst PR_SET_TIMING: c_int = 14; 352b8a62b91Sopenharmony_ci 353b8a62b91Sopenharmony_ci/// Set whether to use (normal, traditional) statistical process timing or accurate 354b8a62b91Sopenharmony_ci/// timestamp-based process timing. 355b8a62b91Sopenharmony_ci/// 356b8a62b91Sopenharmony_ci/// # References 357b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_TIMING,...)`] 358b8a62b91Sopenharmony_ci/// 359b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_TIMING,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 360b8a62b91Sopenharmony_ci#[inline] 361b8a62b91Sopenharmony_cipub fn set_timing_method(method: TimingMethod) -> io::Result<()> { 362b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_TIMING, method as usize as *mut _) }.map(|_r| ()) 363b8a62b91Sopenharmony_ci} 364b8a62b91Sopenharmony_ci 365b8a62b91Sopenharmony_ci// 366b8a62b91Sopenharmony_ci// PR_GET_ENDIAN/PR_SET_ENDIAN 367b8a62b91Sopenharmony_ci// 368b8a62b91Sopenharmony_ci 369b8a62b91Sopenharmony_ciconst PR_GET_ENDIAN: c_int = 19; 370b8a62b91Sopenharmony_ci 371b8a62b91Sopenharmony_ciconst PR_ENDIAN_BIG: u32 = 0; 372b8a62b91Sopenharmony_ciconst PR_ENDIAN_LITTLE: u32 = 1; 373b8a62b91Sopenharmony_ciconst PR_ENDIAN_PPC_LITTLE: u32 = 2; 374b8a62b91Sopenharmony_ci 375b8a62b91Sopenharmony_ci/// `PR_ENDIAN_*`. 376b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 377b8a62b91Sopenharmony_ci#[repr(u32)] 378b8a62b91Sopenharmony_cipub enum EndianMode { 379b8a62b91Sopenharmony_ci /// Big endian mode. 380b8a62b91Sopenharmony_ci Big = PR_ENDIAN_BIG, 381b8a62b91Sopenharmony_ci /// True little endian mode. 382b8a62b91Sopenharmony_ci Little = PR_ENDIAN_LITTLE, 383b8a62b91Sopenharmony_ci /// `PowerPC` pseudo little endian. 384b8a62b91Sopenharmony_ci PowerPCLittle = PR_ENDIAN_PPC_LITTLE, 385b8a62b91Sopenharmony_ci} 386b8a62b91Sopenharmony_ci 387b8a62b91Sopenharmony_ciimpl TryFrom<u32> for EndianMode { 388b8a62b91Sopenharmony_ci type Error = io::Errno; 389b8a62b91Sopenharmony_ci 390b8a62b91Sopenharmony_ci fn try_from(value: u32) -> Result<Self, Self::Error> { 391b8a62b91Sopenharmony_ci match value { 392b8a62b91Sopenharmony_ci PR_ENDIAN_BIG => Ok(Self::Big), 393b8a62b91Sopenharmony_ci PR_ENDIAN_LITTLE => Ok(Self::Little), 394b8a62b91Sopenharmony_ci PR_ENDIAN_PPC_LITTLE => Ok(Self::PowerPCLittle), 395b8a62b91Sopenharmony_ci _ => Err(io::Errno::RANGE), 396b8a62b91Sopenharmony_ci } 397b8a62b91Sopenharmony_ci } 398b8a62b91Sopenharmony_ci} 399b8a62b91Sopenharmony_ci 400b8a62b91Sopenharmony_ci/// Get the endianness of the calling process. 401b8a62b91Sopenharmony_ci/// 402b8a62b91Sopenharmony_ci/// # References 403b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_ENDIAN,...)`] 404b8a62b91Sopenharmony_ci/// 405b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_ENDIAN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 406b8a62b91Sopenharmony_ci#[inline] 407b8a62b91Sopenharmony_cipub fn endian_mode() -> io::Result<EndianMode> { 408b8a62b91Sopenharmony_ci unsafe { prctl_get_at_arg2::<c_uint, _>(PR_GET_ENDIAN) } 409b8a62b91Sopenharmony_ci} 410b8a62b91Sopenharmony_ci 411b8a62b91Sopenharmony_ciconst PR_SET_ENDIAN: c_int = 20; 412b8a62b91Sopenharmony_ci 413b8a62b91Sopenharmony_ci/// Set the endianness of the calling process. 414b8a62b91Sopenharmony_ci/// 415b8a62b91Sopenharmony_ci/// # References 416b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_ENDIAN,...)`] 417b8a62b91Sopenharmony_ci/// 418b8a62b91Sopenharmony_ci/// # Safety 419b8a62b91Sopenharmony_ci/// 420b8a62b91Sopenharmony_ci/// Please ensure the conditions necessary to safely call this function, 421b8a62b91Sopenharmony_ci/// as detailed in the references above. 422b8a62b91Sopenharmony_ci/// 423b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_ENDIAN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 424b8a62b91Sopenharmony_ci#[inline] 425b8a62b91Sopenharmony_cipub unsafe fn set_endian_mode(mode: EndianMode) -> io::Result<()> { 426b8a62b91Sopenharmony_ci prctl_2args(PR_SET_ENDIAN, mode as usize as *mut _).map(|_r| ()) 427b8a62b91Sopenharmony_ci} 428b8a62b91Sopenharmony_ci 429b8a62b91Sopenharmony_ci// 430b8a62b91Sopenharmony_ci// PR_GET_TSC/PR_SET_TSC 431b8a62b91Sopenharmony_ci// 432b8a62b91Sopenharmony_ci 433b8a62b91Sopenharmony_ciconst PR_GET_TSC: c_int = 25; 434b8a62b91Sopenharmony_ci 435b8a62b91Sopenharmony_ciconst PR_TSC_ENABLE: u32 = 1; 436b8a62b91Sopenharmony_ciconst PR_TSC_SIGSEGV: u32 = 2; 437b8a62b91Sopenharmony_ci 438b8a62b91Sopenharmony_ci/// `PR_TSC_*`. 439b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 440b8a62b91Sopenharmony_ci#[repr(u32)] 441b8a62b91Sopenharmony_cipub enum TimeStampCounterReadability { 442b8a62b91Sopenharmony_ci /// Allow the use of the timestamp counter. 443b8a62b91Sopenharmony_ci Readable = PR_TSC_ENABLE, 444b8a62b91Sopenharmony_ci /// Throw a `SIGSEGV` instead of reading the TSC. 445b8a62b91Sopenharmony_ci RaiseSIGSEGV = PR_TSC_SIGSEGV, 446b8a62b91Sopenharmony_ci} 447b8a62b91Sopenharmony_ci 448b8a62b91Sopenharmony_ciimpl TryFrom<u32> for TimeStampCounterReadability { 449b8a62b91Sopenharmony_ci type Error = io::Errno; 450b8a62b91Sopenharmony_ci 451b8a62b91Sopenharmony_ci fn try_from(value: u32) -> Result<Self, Self::Error> { 452b8a62b91Sopenharmony_ci match value { 453b8a62b91Sopenharmony_ci PR_TSC_ENABLE => Ok(Self::Readable), 454b8a62b91Sopenharmony_ci PR_TSC_SIGSEGV => Ok(Self::RaiseSIGSEGV), 455b8a62b91Sopenharmony_ci _ => Err(io::Errno::RANGE), 456b8a62b91Sopenharmony_ci } 457b8a62b91Sopenharmony_ci } 458b8a62b91Sopenharmony_ci} 459b8a62b91Sopenharmony_ci 460b8a62b91Sopenharmony_ci/// Get the state of the flag determining if the timestamp counter can be read. 461b8a62b91Sopenharmony_ci/// 462b8a62b91Sopenharmony_ci/// # References 463b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_TSC,...)`] 464b8a62b91Sopenharmony_ci/// 465b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_TSC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 466b8a62b91Sopenharmony_ci#[inline] 467b8a62b91Sopenharmony_cipub fn time_stamp_counter_readability() -> io::Result<TimeStampCounterReadability> { 468b8a62b91Sopenharmony_ci unsafe { prctl_get_at_arg2::<c_uint, _>(PR_GET_TSC) } 469b8a62b91Sopenharmony_ci} 470b8a62b91Sopenharmony_ci 471b8a62b91Sopenharmony_ciconst PR_SET_TSC: c_int = 26; 472b8a62b91Sopenharmony_ci 473b8a62b91Sopenharmony_ci/// Set the state of the flag determining if the timestamp counter can be read by the process. 474b8a62b91Sopenharmony_ci/// 475b8a62b91Sopenharmony_ci/// # References 476b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_TSC,...)`] 477b8a62b91Sopenharmony_ci/// 478b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_TSC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 479b8a62b91Sopenharmony_ci#[inline] 480b8a62b91Sopenharmony_cipub fn set_time_stamp_counter_readability( 481b8a62b91Sopenharmony_ci readability: TimeStampCounterReadability, 482b8a62b91Sopenharmony_ci) -> io::Result<()> { 483b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_TSC, readability as usize as *mut _) }.map(|_r| ()) 484b8a62b91Sopenharmony_ci} 485b8a62b91Sopenharmony_ci 486b8a62b91Sopenharmony_ci// 487b8a62b91Sopenharmony_ci// PR_TASK_PERF_EVENTS_DISABLE/PR_TASK_PERF_EVENTS_ENABLE 488b8a62b91Sopenharmony_ci// 489b8a62b91Sopenharmony_ci 490b8a62b91Sopenharmony_ciconst PR_TASK_PERF_EVENTS_DISABLE: c_int = 31; 491b8a62b91Sopenharmony_ciconst PR_TASK_PERF_EVENTS_ENABLE: c_int = 32; 492b8a62b91Sopenharmony_ci 493b8a62b91Sopenharmony_ci/// Enable or disable all performance counters attached to the calling process. 494b8a62b91Sopenharmony_ci/// 495b8a62b91Sopenharmony_ci/// # References 496b8a62b91Sopenharmony_ci/// - [`prctl(PR_TASK_PERF_EVENTS_ENABLE,...)`] 497b8a62b91Sopenharmony_ci/// - [`prctl(PR_TASK_PERF_EVENTS_DISABLE,...)`] 498b8a62b91Sopenharmony_ci/// 499b8a62b91Sopenharmony_ci/// [`prctl(PR_TASK_PERF_EVENTS_ENABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 500b8a62b91Sopenharmony_ci/// [`prctl(PR_TASK_PERF_EVENTS_DISABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 501b8a62b91Sopenharmony_ci#[inline] 502b8a62b91Sopenharmony_cipub fn configure_performance_counters(enable: bool) -> io::Result<()> { 503b8a62b91Sopenharmony_ci let option = if enable { 504b8a62b91Sopenharmony_ci PR_TASK_PERF_EVENTS_ENABLE 505b8a62b91Sopenharmony_ci } else { 506b8a62b91Sopenharmony_ci PR_TASK_PERF_EVENTS_DISABLE 507b8a62b91Sopenharmony_ci }; 508b8a62b91Sopenharmony_ci 509b8a62b91Sopenharmony_ci unsafe { prctl_1arg(option) }.map(|_r| ()) 510b8a62b91Sopenharmony_ci} 511b8a62b91Sopenharmony_ci 512b8a62b91Sopenharmony_ci// 513b8a62b91Sopenharmony_ci// PR_MCE_KILL_GET/PR_MCE_KILL 514b8a62b91Sopenharmony_ci// 515b8a62b91Sopenharmony_ci 516b8a62b91Sopenharmony_ciconst PR_MCE_KILL_GET: c_int = 34; 517b8a62b91Sopenharmony_ci 518b8a62b91Sopenharmony_ciconst PR_MCE_KILL_LATE: u32 = 0; 519b8a62b91Sopenharmony_ciconst PR_MCE_KILL_EARLY: u32 = 1; 520b8a62b91Sopenharmony_ciconst PR_MCE_KILL_DEFAULT: u32 = 2; 521b8a62b91Sopenharmony_ci 522b8a62b91Sopenharmony_ci/// `PR_MCE_KILL_*`. 523b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 524b8a62b91Sopenharmony_ci#[repr(u32)] 525b8a62b91Sopenharmony_cipub enum MachineCheckMemoryCorruptionKillPolicy { 526b8a62b91Sopenharmony_ci /// Late kill policy. 527b8a62b91Sopenharmony_ci Late = PR_MCE_KILL_LATE, 528b8a62b91Sopenharmony_ci /// Early kill policy. 529b8a62b91Sopenharmony_ci Early = PR_MCE_KILL_EARLY, 530b8a62b91Sopenharmony_ci /// System-wide default policy. 531b8a62b91Sopenharmony_ci Default = PR_MCE_KILL_DEFAULT, 532b8a62b91Sopenharmony_ci} 533b8a62b91Sopenharmony_ci 534b8a62b91Sopenharmony_ciimpl TryFrom<u32> for MachineCheckMemoryCorruptionKillPolicy { 535b8a62b91Sopenharmony_ci type Error = io::Errno; 536b8a62b91Sopenharmony_ci 537b8a62b91Sopenharmony_ci fn try_from(value: u32) -> Result<Self, Self::Error> { 538b8a62b91Sopenharmony_ci match value { 539b8a62b91Sopenharmony_ci PR_MCE_KILL_LATE => Ok(Self::Late), 540b8a62b91Sopenharmony_ci PR_MCE_KILL_EARLY => Ok(Self::Early), 541b8a62b91Sopenharmony_ci PR_MCE_KILL_DEFAULT => Ok(Self::Default), 542b8a62b91Sopenharmony_ci _ => Err(io::Errno::RANGE), 543b8a62b91Sopenharmony_ci } 544b8a62b91Sopenharmony_ci } 545b8a62b91Sopenharmony_ci} 546b8a62b91Sopenharmony_ci 547b8a62b91Sopenharmony_ci/// Get the current per-process machine check kill policy. 548b8a62b91Sopenharmony_ci/// 549b8a62b91Sopenharmony_ci/// # References 550b8a62b91Sopenharmony_ci/// - [`prctl(PR_MCE_KILL_GET,...)`] 551b8a62b91Sopenharmony_ci/// 552b8a62b91Sopenharmony_ci/// [`prctl(PR_MCE_KILL_GET,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 553b8a62b91Sopenharmony_ci#[inline] 554b8a62b91Sopenharmony_cipub fn machine_check_memory_corruption_kill_policy( 555b8a62b91Sopenharmony_ci) -> io::Result<MachineCheckMemoryCorruptionKillPolicy> { 556b8a62b91Sopenharmony_ci let r = unsafe { prctl_1arg(PR_MCE_KILL_GET)? } as c_uint; 557b8a62b91Sopenharmony_ci MachineCheckMemoryCorruptionKillPolicy::try_from(r) 558b8a62b91Sopenharmony_ci} 559b8a62b91Sopenharmony_ci 560b8a62b91Sopenharmony_ciconst PR_MCE_KILL: c_int = 33; 561b8a62b91Sopenharmony_ci 562b8a62b91Sopenharmony_ciconst PR_MCE_KILL_CLEAR: usize = 0; 563b8a62b91Sopenharmony_ciconst PR_MCE_KILL_SET: usize = 1; 564b8a62b91Sopenharmony_ci 565b8a62b91Sopenharmony_ci/// Set the machine check memory corruption kill policy for the calling thread. 566b8a62b91Sopenharmony_ci/// 567b8a62b91Sopenharmony_ci/// # References 568b8a62b91Sopenharmony_ci/// - [`prctl(PR_MCE_KILL,...)`] 569b8a62b91Sopenharmony_ci/// 570b8a62b91Sopenharmony_ci/// [`prctl(PR_MCE_KILL,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 571b8a62b91Sopenharmony_ci#[inline] 572b8a62b91Sopenharmony_cipub fn set_machine_check_memory_corruption_kill_policy( 573b8a62b91Sopenharmony_ci policy: Option<MachineCheckMemoryCorruptionKillPolicy>, 574b8a62b91Sopenharmony_ci) -> io::Result<()> { 575b8a62b91Sopenharmony_ci let (sub_operation, policy) = if let Some(policy) = policy { 576b8a62b91Sopenharmony_ci (PR_MCE_KILL_SET, policy as usize as *mut _) 577b8a62b91Sopenharmony_ci } else { 578b8a62b91Sopenharmony_ci (PR_MCE_KILL_CLEAR, ptr::null_mut()) 579b8a62b91Sopenharmony_ci }; 580b8a62b91Sopenharmony_ci 581b8a62b91Sopenharmony_ci unsafe { prctl_3args(PR_MCE_KILL, sub_operation as *mut _, policy) }.map(|_r| ()) 582b8a62b91Sopenharmony_ci} 583b8a62b91Sopenharmony_ci 584b8a62b91Sopenharmony_ci// 585b8a62b91Sopenharmony_ci// PR_SET_MM 586b8a62b91Sopenharmony_ci// 587b8a62b91Sopenharmony_ci 588b8a62b91Sopenharmony_ciconst PR_SET_MM: c_int = 35; 589b8a62b91Sopenharmony_ci 590b8a62b91Sopenharmony_ciconst PR_SET_MM_START_CODE: u32 = 1; 591b8a62b91Sopenharmony_ciconst PR_SET_MM_END_CODE: u32 = 2; 592b8a62b91Sopenharmony_ciconst PR_SET_MM_START_DATA: u32 = 3; 593b8a62b91Sopenharmony_ciconst PR_SET_MM_END_DATA: u32 = 4; 594b8a62b91Sopenharmony_ciconst PR_SET_MM_START_STACK: u32 = 5; 595b8a62b91Sopenharmony_ciconst PR_SET_MM_START_BRK: u32 = 6; 596b8a62b91Sopenharmony_ciconst PR_SET_MM_BRK: u32 = 7; 597b8a62b91Sopenharmony_ciconst PR_SET_MM_ARG_START: u32 = 8; 598b8a62b91Sopenharmony_ciconst PR_SET_MM_ARG_END: u32 = 9; 599b8a62b91Sopenharmony_ciconst PR_SET_MM_ENV_START: u32 = 10; 600b8a62b91Sopenharmony_ciconst PR_SET_MM_ENV_END: u32 = 11; 601b8a62b91Sopenharmony_ciconst PR_SET_MM_AUXV: usize = 12; 602b8a62b91Sopenharmony_ciconst PR_SET_MM_EXE_FILE: usize = 13; 603b8a62b91Sopenharmony_ciconst PR_SET_MM_MAP: usize = 14; 604b8a62b91Sopenharmony_ciconst PR_SET_MM_MAP_SIZE: usize = 15; 605b8a62b91Sopenharmony_ci 606b8a62b91Sopenharmony_ci/// `PR_SET_MM_*`. 607b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 608b8a62b91Sopenharmony_ci#[repr(u32)] 609b8a62b91Sopenharmony_cipub enum VirtualMemoryMapAddress { 610b8a62b91Sopenharmony_ci /// Set the address above which the program text can run. 611b8a62b91Sopenharmony_ci CodeStart = PR_SET_MM_START_CODE, 612b8a62b91Sopenharmony_ci /// Set the address below which the program text can run. 613b8a62b91Sopenharmony_ci CodeEnd = PR_SET_MM_END_CODE, 614b8a62b91Sopenharmony_ci /// Set the address above which initialized and uninitialized (bss) data are placed. 615b8a62b91Sopenharmony_ci DataStart = PR_SET_MM_START_DATA, 616b8a62b91Sopenharmony_ci /// Set the address below which initialized and uninitialized (bss) data are placed. 617b8a62b91Sopenharmony_ci DataEnd = PR_SET_MM_END_DATA, 618b8a62b91Sopenharmony_ci /// Set the start address of the stack. 619b8a62b91Sopenharmony_ci StackStart = PR_SET_MM_START_STACK, 620b8a62b91Sopenharmony_ci /// Set the address above which the program heap can be expanded with `brk` call. 621b8a62b91Sopenharmony_ci BrkStart = PR_SET_MM_START_BRK, 622b8a62b91Sopenharmony_ci /// Set the current `brk` value. 623b8a62b91Sopenharmony_ci BrkCurrent = PR_SET_MM_BRK, 624b8a62b91Sopenharmony_ci /// Set the address above which the program command line is placed. 625b8a62b91Sopenharmony_ci ArgStart = PR_SET_MM_ARG_START, 626b8a62b91Sopenharmony_ci /// Set the address below which the program command line is placed. 627b8a62b91Sopenharmony_ci ArgEnd = PR_SET_MM_ARG_END, 628b8a62b91Sopenharmony_ci /// Set the address above which the program environment is placed. 629b8a62b91Sopenharmony_ci EnvironmentStart = PR_SET_MM_ENV_START, 630b8a62b91Sopenharmony_ci /// Set the address below which the program environment is placed. 631b8a62b91Sopenharmony_ci EnvironmentEnd = PR_SET_MM_ENV_END, 632b8a62b91Sopenharmony_ci} 633b8a62b91Sopenharmony_ci 634b8a62b91Sopenharmony_ci/// Modify certain kernel memory map descriptor addresses of the calling process. 635b8a62b91Sopenharmony_ci/// 636b8a62b91Sopenharmony_ci/// # References 637b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_MM,...)`] 638b8a62b91Sopenharmony_ci/// 639b8a62b91Sopenharmony_ci/// # Safety 640b8a62b91Sopenharmony_ci/// 641b8a62b91Sopenharmony_ci/// Please ensure the conditions necessary to safely call this function, 642b8a62b91Sopenharmony_ci/// as detailed in the references above. 643b8a62b91Sopenharmony_ci/// 644b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_MM,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 645b8a62b91Sopenharmony_ci#[inline] 646b8a62b91Sopenharmony_cipub unsafe fn set_virtual_memory_map_address( 647b8a62b91Sopenharmony_ci option: VirtualMemoryMapAddress, 648b8a62b91Sopenharmony_ci address: Option<NonNull<c_void>>, 649b8a62b91Sopenharmony_ci) -> io::Result<()> { 650b8a62b91Sopenharmony_ci let address = address.map_or_else(ptr::null_mut, NonNull::as_ptr); 651b8a62b91Sopenharmony_ci prctl_3args(PR_SET_MM, option as usize as *mut _, address).map(|_r| ()) 652b8a62b91Sopenharmony_ci} 653b8a62b91Sopenharmony_ci 654b8a62b91Sopenharmony_ci/// Supersede the `/proc/pid/exe` symbolic link with a new one pointing to a new executable file. 655b8a62b91Sopenharmony_ci/// 656b8a62b91Sopenharmony_ci/// # References 657b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_MM,PR_SET_MM_EXE_FILE,...)`] 658b8a62b91Sopenharmony_ci/// 659b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_MM,PR_SET_MM_EXE_FILE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 660b8a62b91Sopenharmony_ci#[inline] 661b8a62b91Sopenharmony_cipub fn set_executable_file(fd: BorrowedFd) -> io::Result<()> { 662b8a62b91Sopenharmony_ci let fd = usize::try_from(fd.as_raw_fd()).map_err(|_r| io::Errno::RANGE)?; 663b8a62b91Sopenharmony_ci unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_EXE_FILE as *mut _, fd as *mut _) }.map(|_r| ()) 664b8a62b91Sopenharmony_ci} 665b8a62b91Sopenharmony_ci 666b8a62b91Sopenharmony_ci/// Set a new auxiliary vector. 667b8a62b91Sopenharmony_ci/// 668b8a62b91Sopenharmony_ci/// # References 669b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_MM,PR_SET_MM_AUXV,...)`] 670b8a62b91Sopenharmony_ci/// 671b8a62b91Sopenharmony_ci/// # Safety 672b8a62b91Sopenharmony_ci/// 673b8a62b91Sopenharmony_ci/// Please ensure the conditions necessary to safely call this function, 674b8a62b91Sopenharmony_ci/// as detailed in the references above. 675b8a62b91Sopenharmony_ci/// 676b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_MM,PR_SET_MM_AUXV,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 677b8a62b91Sopenharmony_ci#[inline] 678b8a62b91Sopenharmony_cipub unsafe fn set_auxiliary_vector(auxv: &[*const c_void]) -> io::Result<()> { 679b8a62b91Sopenharmony_ci syscalls::prctl( 680b8a62b91Sopenharmony_ci PR_SET_MM, 681b8a62b91Sopenharmony_ci PR_SET_MM_AUXV as *mut _, 682b8a62b91Sopenharmony_ci auxv.as_ptr() as *mut _, 683b8a62b91Sopenharmony_ci auxv.len() as *mut _, 684b8a62b91Sopenharmony_ci ptr::null_mut(), 685b8a62b91Sopenharmony_ci ) 686b8a62b91Sopenharmony_ci .map(|_r| ()) 687b8a62b91Sopenharmony_ci} 688b8a62b91Sopenharmony_ci 689b8a62b91Sopenharmony_ci/// Get the size of the [`PrctlMmMap`] the kernel expects. 690b8a62b91Sopenharmony_ci/// 691b8a62b91Sopenharmony_ci/// # References 692b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_MM,PR_SET_MM_MAP_SIZE,...)`] 693b8a62b91Sopenharmony_ci/// 694b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_MM,PR_SET_MM_MAP_SIZE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 695b8a62b91Sopenharmony_ci#[inline] 696b8a62b91Sopenharmony_cipub fn virtual_memory_map_config_struct_size() -> io::Result<usize> { 697b8a62b91Sopenharmony_ci let mut value: c_uint = 0; 698b8a62b91Sopenharmony_ci let value_ptr = (&mut value) as *mut c_uint; 699b8a62b91Sopenharmony_ci unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_MAP_SIZE as *mut _, value_ptr.cast())? }; 700b8a62b91Sopenharmony_ci Ok(value as usize) 701b8a62b91Sopenharmony_ci} 702b8a62b91Sopenharmony_ci 703b8a62b91Sopenharmony_ci/// This structure provides new memory descriptor map which mostly modifies `/proc/pid/stat[m]` 704b8a62b91Sopenharmony_ci/// output for a task. 705b8a62b91Sopenharmony_ci/// This mostly done in a sake of checkpoint/restore functionality. 706b8a62b91Sopenharmony_ci#[repr(C)] 707b8a62b91Sopenharmony_ci#[derive(Debug, Clone)] 708b8a62b91Sopenharmony_cipub struct PrctlMmMap { 709b8a62b91Sopenharmony_ci /// Code section start address. 710b8a62b91Sopenharmony_ci pub start_code: u64, 711b8a62b91Sopenharmony_ci /// Code section end address. 712b8a62b91Sopenharmony_ci pub end_code: u64, 713b8a62b91Sopenharmony_ci /// Data section start address. 714b8a62b91Sopenharmony_ci pub start_data: u64, 715b8a62b91Sopenharmony_ci /// Data section end address. 716b8a62b91Sopenharmony_ci pub end_data: u64, 717b8a62b91Sopenharmony_ci /// brk() start address. 718b8a62b91Sopenharmony_ci pub start_brk: u64, 719b8a62b91Sopenharmony_ci /// brk() current address. 720b8a62b91Sopenharmony_ci pub brk: u64, 721b8a62b91Sopenharmony_ci /// Stack start address. 722b8a62b91Sopenharmony_ci pub start_stack: u64, 723b8a62b91Sopenharmony_ci /// Program command line start address. 724b8a62b91Sopenharmony_ci pub arg_start: u64, 725b8a62b91Sopenharmony_ci /// Program command line end address. 726b8a62b91Sopenharmony_ci pub arg_end: u64, 727b8a62b91Sopenharmony_ci /// Program environment start address. 728b8a62b91Sopenharmony_ci pub env_start: u64, 729b8a62b91Sopenharmony_ci /// Program environment end address. 730b8a62b91Sopenharmony_ci pub env_end: u64, 731b8a62b91Sopenharmony_ci /// Auxiliary vector start address. 732b8a62b91Sopenharmony_ci pub auxv: *mut u64, 733b8a62b91Sopenharmony_ci /// Auxiliary vector size. 734b8a62b91Sopenharmony_ci pub auxv_size: u32, 735b8a62b91Sopenharmony_ci /// File descriptor of executable file that was used to create this process. 736b8a62b91Sopenharmony_ci pub exe_fd: u32, 737b8a62b91Sopenharmony_ci} 738b8a62b91Sopenharmony_ci 739b8a62b91Sopenharmony_ci/// Provides one-shot access to all the addresses by passing in a [`PrctlMmMap`]. 740b8a62b91Sopenharmony_ci/// 741b8a62b91Sopenharmony_ci/// # References 742b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_MM,PR_SET_MM_MAP,...)`] 743b8a62b91Sopenharmony_ci/// 744b8a62b91Sopenharmony_ci/// # Safety 745b8a62b91Sopenharmony_ci/// 746b8a62b91Sopenharmony_ci/// Please ensure the conditions necessary to safely call this function, 747b8a62b91Sopenharmony_ci/// as detailed in the references above. 748b8a62b91Sopenharmony_ci/// 749b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_MM,PR_SET_MM_MAP,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 750b8a62b91Sopenharmony_ci#[inline] 751b8a62b91Sopenharmony_cipub unsafe fn configure_virtual_memory_map(config: &PrctlMmMap) -> io::Result<()> { 752b8a62b91Sopenharmony_ci syscalls::prctl( 753b8a62b91Sopenharmony_ci PR_SET_MM, 754b8a62b91Sopenharmony_ci PR_SET_MM_MAP as *mut _, 755b8a62b91Sopenharmony_ci config as *const PrctlMmMap as *mut _, 756b8a62b91Sopenharmony_ci mem::size_of::<PrctlMmMap>() as *mut _, 757b8a62b91Sopenharmony_ci ptr::null_mut(), 758b8a62b91Sopenharmony_ci ) 759b8a62b91Sopenharmony_ci .map(|_r| ()) 760b8a62b91Sopenharmony_ci} 761b8a62b91Sopenharmony_ci 762b8a62b91Sopenharmony_ci// 763b8a62b91Sopenharmony_ci// PR_SET_PTRACER 764b8a62b91Sopenharmony_ci// 765b8a62b91Sopenharmony_ci 766b8a62b91Sopenharmony_ciconst PR_SET_PTRACER: c_int = 0x59_61_6d_61; 767b8a62b91Sopenharmony_ci 768b8a62b91Sopenharmony_ciconst PR_SET_PTRACER_ANY: usize = usize::MAX; 769b8a62b91Sopenharmony_ci 770b8a62b91Sopenharmony_ci/// Process ptracer. 771b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 772b8a62b91Sopenharmony_cipub enum PTracer { 773b8a62b91Sopenharmony_ci /// None. 774b8a62b91Sopenharmony_ci None, 775b8a62b91Sopenharmony_ci /// Disable `ptrace` restrictions for the calling process. 776b8a62b91Sopenharmony_ci Any, 777b8a62b91Sopenharmony_ci /// Specific process. 778b8a62b91Sopenharmony_ci ProcessID(Pid), 779b8a62b91Sopenharmony_ci} 780b8a62b91Sopenharmony_ci 781b8a62b91Sopenharmony_ci/// Declare that the ptracer process can `ptrace` the calling process as if it were a direct 782b8a62b91Sopenharmony_ci/// process ancestor. 783b8a62b91Sopenharmony_ci/// 784b8a62b91Sopenharmony_ci/// # References 785b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_PTRACER,...)`] 786b8a62b91Sopenharmony_ci/// 787b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_PTRACER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 788b8a62b91Sopenharmony_ci#[inline] 789b8a62b91Sopenharmony_cipub fn set_ptracer(tracer: PTracer) -> io::Result<()> { 790b8a62b91Sopenharmony_ci let pid = match tracer { 791b8a62b91Sopenharmony_ci PTracer::None => ptr::null_mut(), 792b8a62b91Sopenharmony_ci PTracer::Any => PR_SET_PTRACER_ANY as *mut _, 793b8a62b91Sopenharmony_ci PTracer::ProcessID(pid) => pid.as_raw_nonzero().get() as usize as *mut _, 794b8a62b91Sopenharmony_ci }; 795b8a62b91Sopenharmony_ci 796b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_PTRACER, pid) }.map(|_r| ()) 797b8a62b91Sopenharmony_ci} 798b8a62b91Sopenharmony_ci 799b8a62b91Sopenharmony_ci// 800b8a62b91Sopenharmony_ci// PR_GET_CHILD_SUBREAPER/PR_SET_CHILD_SUBREAPER 801b8a62b91Sopenharmony_ci// 802b8a62b91Sopenharmony_ci 803b8a62b91Sopenharmony_ciconst PR_GET_CHILD_SUBREAPER: c_int = 37; 804b8a62b91Sopenharmony_ci 805b8a62b91Sopenharmony_ci/// Get the `child subreaper` setting of the calling process. 806b8a62b91Sopenharmony_ci/// 807b8a62b91Sopenharmony_ci/// # References 808b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_CHILD_SUBREAPER,...)`] 809b8a62b91Sopenharmony_ci/// 810b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_CHILD_SUBREAPER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 811b8a62b91Sopenharmony_ci#[inline] 812b8a62b91Sopenharmony_cipub fn child_subreaper() -> io::Result<Option<Pid>> { 813b8a62b91Sopenharmony_ci unsafe { 814b8a62b91Sopenharmony_ci let r = prctl_get_at_arg2_optional::<c_uint>(PR_GET_CHILD_SUBREAPER)?; 815b8a62b91Sopenharmony_ci Ok(Pid::from_raw(r as RawPid)) 816b8a62b91Sopenharmony_ci } 817b8a62b91Sopenharmony_ci} 818b8a62b91Sopenharmony_ci 819b8a62b91Sopenharmony_ciconst PR_SET_CHILD_SUBREAPER: c_int = 36; 820b8a62b91Sopenharmony_ci 821b8a62b91Sopenharmony_ci/// Set the `child subreaper` attribute of the calling process. 822b8a62b91Sopenharmony_ci/// 823b8a62b91Sopenharmony_ci/// # References 824b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_CHILD_SUBREAPER,...)`] 825b8a62b91Sopenharmony_ci/// 826b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_CHILD_SUBREAPER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 827b8a62b91Sopenharmony_ci#[inline] 828b8a62b91Sopenharmony_cipub fn set_child_subreaper(pid: Option<Pid>) -> io::Result<()> { 829b8a62b91Sopenharmony_ci let pid = pid.map_or(0_usize, |pid| pid.as_raw_nonzero().get() as usize); 830b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_CHILD_SUBREAPER, pid as *mut _) }.map(|_r| ()) 831b8a62b91Sopenharmony_ci} 832b8a62b91Sopenharmony_ci 833b8a62b91Sopenharmony_ci// 834b8a62b91Sopenharmony_ci// PR_GET_FP_MODE/PR_SET_FP_MODE 835b8a62b91Sopenharmony_ci// 836b8a62b91Sopenharmony_ci 837b8a62b91Sopenharmony_ciconst PR_GET_FP_MODE: c_int = 46; 838b8a62b91Sopenharmony_ci 839b8a62b91Sopenharmony_ciconst PR_FP_MODE_FR: u32 = 1_u32 << 0; 840b8a62b91Sopenharmony_ciconst PR_FP_MODE_FRE: u32 = 1_u32 << 1; 841b8a62b91Sopenharmony_ci 842b8a62b91Sopenharmony_ci/// `PR_FP_MODE_*`. 843b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 844b8a62b91Sopenharmony_ci#[repr(u32)] 845b8a62b91Sopenharmony_cipub enum FloatingPointMode { 846b8a62b91Sopenharmony_ci /// 64-bit floating point registers. 847b8a62b91Sopenharmony_ci FloatingPointRegisters = PR_FP_MODE_FR, 848b8a62b91Sopenharmony_ci /// Enable emulation of 32-bit floating-point mode. 849b8a62b91Sopenharmony_ci FloatingPointEmulation = PR_FP_MODE_FRE, 850b8a62b91Sopenharmony_ci} 851b8a62b91Sopenharmony_ci 852b8a62b91Sopenharmony_ciimpl TryFrom<u32> for FloatingPointMode { 853b8a62b91Sopenharmony_ci type Error = io::Errno; 854b8a62b91Sopenharmony_ci 855b8a62b91Sopenharmony_ci fn try_from(value: u32) -> Result<Self, Self::Error> { 856b8a62b91Sopenharmony_ci match value { 857b8a62b91Sopenharmony_ci PR_FP_MODE_FR => Ok(Self::FloatingPointRegisters), 858b8a62b91Sopenharmony_ci PR_FP_MODE_FRE => Ok(Self::FloatingPointEmulation), 859b8a62b91Sopenharmony_ci _ => Err(io::Errno::RANGE), 860b8a62b91Sopenharmony_ci } 861b8a62b91Sopenharmony_ci } 862b8a62b91Sopenharmony_ci} 863b8a62b91Sopenharmony_ci 864b8a62b91Sopenharmony_ci/// Get the current floating point mode. 865b8a62b91Sopenharmony_ci/// 866b8a62b91Sopenharmony_ci/// # References 867b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_FP_MODE,...)`] 868b8a62b91Sopenharmony_ci/// 869b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_FP_MODE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 870b8a62b91Sopenharmony_ci#[inline] 871b8a62b91Sopenharmony_cipub fn floating_point_mode() -> io::Result<FloatingPointMode> { 872b8a62b91Sopenharmony_ci let r = unsafe { prctl_1arg(PR_GET_FP_MODE)? } as c_uint; 873b8a62b91Sopenharmony_ci FloatingPointMode::try_from(r) 874b8a62b91Sopenharmony_ci} 875b8a62b91Sopenharmony_ci 876b8a62b91Sopenharmony_ciconst PR_SET_FP_MODE: c_int = 45; 877b8a62b91Sopenharmony_ci 878b8a62b91Sopenharmony_ci/// Allow control of the floating point mode from user space. 879b8a62b91Sopenharmony_ci/// 880b8a62b91Sopenharmony_ci/// # References 881b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_FP_MODE,...)`] 882b8a62b91Sopenharmony_ci/// 883b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_FP_MODE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 884b8a62b91Sopenharmony_ci#[inline] 885b8a62b91Sopenharmony_cipub fn set_floating_point_mode(mode: FloatingPointMode) -> io::Result<()> { 886b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_FP_MODE, mode as usize as *mut _) }.map(|_r| ()) 887b8a62b91Sopenharmony_ci} 888b8a62b91Sopenharmony_ci 889b8a62b91Sopenharmony_ci// 890b8a62b91Sopenharmony_ci// PR_GET_SPECULATION_CTRL/PR_SET_SPECULATION_CTRL 891b8a62b91Sopenharmony_ci// 892b8a62b91Sopenharmony_ci 893b8a62b91Sopenharmony_ciconst PR_GET_SPECULATION_CTRL: c_int = 52; 894b8a62b91Sopenharmony_ci 895b8a62b91Sopenharmony_ciconst PR_SPEC_STORE_BYPASS: u32 = 0; 896b8a62b91Sopenharmony_ciconst PR_SPEC_INDIRECT_BRANCH: u32 = 1; 897b8a62b91Sopenharmony_ciconst PR_SPEC_L1D_FLUSH: u32 = 2; 898b8a62b91Sopenharmony_ci 899b8a62b91Sopenharmony_ci/// `PR_SPEC_*`. 900b8a62b91Sopenharmony_ci#[derive(Copy, Clone, Debug, Eq, PartialEq)] 901b8a62b91Sopenharmony_ci#[repr(u32)] 902b8a62b91Sopenharmony_cipub enum SpeculationFeature { 903b8a62b91Sopenharmony_ci /// Set the state of the speculative store bypass misfeature. 904b8a62b91Sopenharmony_ci SpeculativeStoreBypass = PR_SPEC_STORE_BYPASS, 905b8a62b91Sopenharmony_ci /// Set the state of the indirect branch speculation misfeature. 906b8a62b91Sopenharmony_ci IndirectBranchSpeculation = PR_SPEC_INDIRECT_BRANCH, 907b8a62b91Sopenharmony_ci /// Flush L1D Cache on context switch out of the task. 908b8a62b91Sopenharmony_ci FlushL1DCacheOnContextSwitchOutOfTask = PR_SPEC_L1D_FLUSH, 909b8a62b91Sopenharmony_ci} 910b8a62b91Sopenharmony_ci 911b8a62b91Sopenharmony_ciimpl TryFrom<u32> for SpeculationFeature { 912b8a62b91Sopenharmony_ci type Error = io::Errno; 913b8a62b91Sopenharmony_ci 914b8a62b91Sopenharmony_ci fn try_from(value: u32) -> Result<Self, Self::Error> { 915b8a62b91Sopenharmony_ci match value { 916b8a62b91Sopenharmony_ci PR_SPEC_STORE_BYPASS => Ok(Self::SpeculativeStoreBypass), 917b8a62b91Sopenharmony_ci PR_SPEC_INDIRECT_BRANCH => Ok(Self::IndirectBranchSpeculation), 918b8a62b91Sopenharmony_ci PR_SPEC_L1D_FLUSH => Ok(Self::FlushL1DCacheOnContextSwitchOutOfTask), 919b8a62b91Sopenharmony_ci _ => Err(io::Errno::RANGE), 920b8a62b91Sopenharmony_ci } 921b8a62b91Sopenharmony_ci } 922b8a62b91Sopenharmony_ci} 923b8a62b91Sopenharmony_ci 924b8a62b91Sopenharmony_cibitflags! { 925b8a62b91Sopenharmony_ci /// `PR_SPEC_*`. 926b8a62b91Sopenharmony_ci pub struct SpeculationFeatureControl: u32 { 927b8a62b91Sopenharmony_ci /// The speculation feature is enabled, mitigation is disabled. 928b8a62b91Sopenharmony_ci const ENABLE = 1_u32 << 1; 929b8a62b91Sopenharmony_ci /// The speculation feature is disabled, mitigation is enabled. 930b8a62b91Sopenharmony_ci const DISABLE = 1_u32 << 2; 931b8a62b91Sopenharmony_ci /// The speculation feature is disabled, mitigation is enabled, and it cannot be undone. 932b8a62b91Sopenharmony_ci const FORCE_DISABLE = 1_u32 << 3; 933b8a62b91Sopenharmony_ci /// The speculation feature is disabled, mitigation is enabled, and the state will be cleared on `execve`. 934b8a62b91Sopenharmony_ci const DISABLE_NOEXEC = 1_u32 << 4; 935b8a62b91Sopenharmony_ci } 936b8a62b91Sopenharmony_ci} 937b8a62b91Sopenharmony_ci 938b8a62b91Sopenharmony_cibitflags! { 939b8a62b91Sopenharmony_ci /// Zero means the processors are not vulnerable. 940b8a62b91Sopenharmony_ci pub struct SpeculationFeatureState: u32 { 941b8a62b91Sopenharmony_ci /// Mitigation can be controlled per thread by `PR_SET_SPECULATION_CTRL`. 942b8a62b91Sopenharmony_ci const PRCTL = 1_u32 << 0; 943b8a62b91Sopenharmony_ci /// The speculation feature is enabled, mitigation is disabled. 944b8a62b91Sopenharmony_ci const ENABLE = 1_u32 << 1; 945b8a62b91Sopenharmony_ci /// The speculation feature is disabled, mitigation is enabled. 946b8a62b91Sopenharmony_ci const DISABLE = 1_u32 << 2; 947b8a62b91Sopenharmony_ci /// The speculation feature is disabled, mitigation is enabled, and it cannot be undone. 948b8a62b91Sopenharmony_ci const FORCE_DISABLE = 1_u32 << 3; 949b8a62b91Sopenharmony_ci /// The speculation feature is disabled, mitigation is enabled, and the state will be cleared on `execve`. 950b8a62b91Sopenharmony_ci const DISABLE_NOEXEC = 1_u32 << 4; 951b8a62b91Sopenharmony_ci } 952b8a62b91Sopenharmony_ci} 953b8a62b91Sopenharmony_ci 954b8a62b91Sopenharmony_ci/// Get the state of the speculation misfeature. 955b8a62b91Sopenharmony_ci/// 956b8a62b91Sopenharmony_ci/// # References 957b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_SPECULATION_CTRL,...)`] 958b8a62b91Sopenharmony_ci/// 959b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_SPECULATION_CTRL,...)`]: https://www.kernel.org/doc/html/v5.18/userspace-api/spec_ctrl.html 960b8a62b91Sopenharmony_ci#[inline] 961b8a62b91Sopenharmony_cipub fn speculative_feature_state( 962b8a62b91Sopenharmony_ci feature: SpeculationFeature, 963b8a62b91Sopenharmony_ci) -> io::Result<Option<SpeculationFeatureState>> { 964b8a62b91Sopenharmony_ci let r = unsafe { prctl_2args(PR_GET_SPECULATION_CTRL, feature as usize as *mut _)? } as c_uint; 965b8a62b91Sopenharmony_ci Ok(SpeculationFeatureState::from_bits(r)) 966b8a62b91Sopenharmony_ci} 967b8a62b91Sopenharmony_ci 968b8a62b91Sopenharmony_ciconst PR_SET_SPECULATION_CTRL: c_int = 53; 969b8a62b91Sopenharmony_ci 970b8a62b91Sopenharmony_ci/// Sets the state of the speculation misfeature. 971b8a62b91Sopenharmony_ci/// 972b8a62b91Sopenharmony_ci/// # References 973b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_SPECULATION_CTRL,...)`] 974b8a62b91Sopenharmony_ci/// 975b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_SPECULATION_CTRL,...)`]: https://www.kernel.org/doc/html/v5.18/userspace-api/spec_ctrl.html 976b8a62b91Sopenharmony_ci#[inline] 977b8a62b91Sopenharmony_cipub fn control_speculative_feature( 978b8a62b91Sopenharmony_ci feature: SpeculationFeature, 979b8a62b91Sopenharmony_ci config: SpeculationFeatureControl, 980b8a62b91Sopenharmony_ci) -> io::Result<()> { 981b8a62b91Sopenharmony_ci let feature = feature as usize as *mut _; 982b8a62b91Sopenharmony_ci let config = config.bits() as usize as *mut _; 983b8a62b91Sopenharmony_ci unsafe { prctl_3args(PR_SET_SPECULATION_CTRL, feature, config) }.map(|_r| ()) 984b8a62b91Sopenharmony_ci} 985b8a62b91Sopenharmony_ci 986b8a62b91Sopenharmony_ci// 987b8a62b91Sopenharmony_ci// PR_GET_IO_FLUSHER/PR_SET_IO_FLUSHER 988b8a62b91Sopenharmony_ci// 989b8a62b91Sopenharmony_ci 990b8a62b91Sopenharmony_ciconst PR_GET_IO_FLUSHER: c_int = 58; 991b8a62b91Sopenharmony_ci 992b8a62b91Sopenharmony_ci/// Get the `IO_FLUSHER` state of the caller. 993b8a62b91Sopenharmony_ci/// 994b8a62b91Sopenharmony_ci/// # References 995b8a62b91Sopenharmony_ci/// - [`prctl(PR_GET_IO_FLUSHER,...)`] 996b8a62b91Sopenharmony_ci/// 997b8a62b91Sopenharmony_ci/// [`prctl(PR_GET_IO_FLUSHER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 998b8a62b91Sopenharmony_ci#[inline] 999b8a62b91Sopenharmony_cipub fn is_io_flusher() -> io::Result<bool> { 1000b8a62b91Sopenharmony_ci unsafe { prctl_1arg(PR_GET_IO_FLUSHER) }.map(|r| r != 0) 1001b8a62b91Sopenharmony_ci} 1002b8a62b91Sopenharmony_ci 1003b8a62b91Sopenharmony_ciconst PR_SET_IO_FLUSHER: c_int = 57; 1004b8a62b91Sopenharmony_ci 1005b8a62b91Sopenharmony_ci/// Put the process in the `IO_FLUSHER` state, allowing it to make progress when 1006b8a62b91Sopenharmony_ci/// allocating memory. 1007b8a62b91Sopenharmony_ci/// 1008b8a62b91Sopenharmony_ci/// # References 1009b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_IO_FLUSHER,...)`] 1010b8a62b91Sopenharmony_ci/// 1011b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_IO_FLUSHER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html 1012b8a62b91Sopenharmony_ci#[inline] 1013b8a62b91Sopenharmony_cipub fn configure_io_flusher_behavior(enable: bool) -> io::Result<()> { 1014b8a62b91Sopenharmony_ci unsafe { prctl_2args(PR_SET_IO_FLUSHER, enable as usize as *mut _) }.map(|_r| ()) 1015b8a62b91Sopenharmony_ci} 1016b8a62b91Sopenharmony_ci 1017b8a62b91Sopenharmony_ci// 1018b8a62b91Sopenharmony_ci// PR_PAC_GET_ENABLED_KEYS/PR_PAC_SET_ENABLED_KEYS 1019b8a62b91Sopenharmony_ci// 1020b8a62b91Sopenharmony_ci 1021b8a62b91Sopenharmony_ciconst PR_PAC_GET_ENABLED_KEYS: c_int = 61; 1022b8a62b91Sopenharmony_ci 1023b8a62b91Sopenharmony_cibitflags! { 1024b8a62b91Sopenharmony_ci /// `PR_PAC_AP*`. 1025b8a62b91Sopenharmony_ci pub struct PointerAuthenticationKeys: u32 { 1026b8a62b91Sopenharmony_ci /// Instruction authentication key `A`. 1027b8a62b91Sopenharmony_ci const INSTRUCTION_AUTHENTICATION_KEY_A = 1_u32 << 0; 1028b8a62b91Sopenharmony_ci /// Instruction authentication key `B`. 1029b8a62b91Sopenharmony_ci const INSTRUCTION_AUTHENTICATION_KEY_B = 1_u32 << 1; 1030b8a62b91Sopenharmony_ci /// Data authentication key `A`. 1031b8a62b91Sopenharmony_ci const DATA_AUTHENTICATION_KEY_A = 1_u32 << 2; 1032b8a62b91Sopenharmony_ci /// Data authentication key `B`. 1033b8a62b91Sopenharmony_ci const DATA_AUTHENTICATION_KEY_B = 1_u32 << 3; 1034b8a62b91Sopenharmony_ci /// Generic authentication `A` key. 1035b8a62b91Sopenharmony_ci const GENERIC_AUTHENTICATION_KEY_A = 1_u32 << 4; 1036b8a62b91Sopenharmony_ci } 1037b8a62b91Sopenharmony_ci} 1038b8a62b91Sopenharmony_ci 1039b8a62b91Sopenharmony_ci/// Get enabled pointer authentication keys. 1040b8a62b91Sopenharmony_ci/// 1041b8a62b91Sopenharmony_ci/// # References 1042b8a62b91Sopenharmony_ci/// - [`prctl(PR_PAC_GET_ENABLED_KEYS,...)`] 1043b8a62b91Sopenharmony_ci/// 1044b8a62b91Sopenharmony_ci/// [`prctl(PR_PAC_GET_ENABLED_KEYS,...)`]: https://www.kernel.org/doc/html/v5.18/arm64/pointer-authentication.html 1045b8a62b91Sopenharmony_ci#[inline] 1046b8a62b91Sopenharmony_cipub fn enabled_pointer_authentication_keys() -> io::Result<PointerAuthenticationKeys> { 1047b8a62b91Sopenharmony_ci let r = unsafe { prctl_1arg(PR_PAC_GET_ENABLED_KEYS)? } as c_uint; 1048b8a62b91Sopenharmony_ci PointerAuthenticationKeys::from_bits(r).ok_or(io::Errno::RANGE) 1049b8a62b91Sopenharmony_ci} 1050b8a62b91Sopenharmony_ci 1051b8a62b91Sopenharmony_ciconst PR_PAC_SET_ENABLED_KEYS: c_int = 60; 1052b8a62b91Sopenharmony_ci 1053b8a62b91Sopenharmony_ci/// Set enabled pointer authentication keys. 1054b8a62b91Sopenharmony_ci/// 1055b8a62b91Sopenharmony_ci/// # References 1056b8a62b91Sopenharmony_ci/// - [`prctl(PR_PAC_SET_ENABLED_KEYS,...)`] 1057b8a62b91Sopenharmony_ci/// 1058b8a62b91Sopenharmony_ci/// # Safety 1059b8a62b91Sopenharmony_ci/// 1060b8a62b91Sopenharmony_ci/// Please ensure the conditions necessary to safely call this function, 1061b8a62b91Sopenharmony_ci/// as detailed in the references above. 1062b8a62b91Sopenharmony_ci/// 1063b8a62b91Sopenharmony_ci/// [`prctl(PR_PAC_SET_ENABLED_KEYS,...)`]: https://www.kernel.org/doc/html/v5.18/arm64/pointer-authentication.html 1064b8a62b91Sopenharmony_ci#[inline] 1065b8a62b91Sopenharmony_cipub unsafe fn configure_pointer_authentication_keys( 1066b8a62b91Sopenharmony_ci config: impl Iterator<Item = (PointerAuthenticationKeys, bool)>, 1067b8a62b91Sopenharmony_ci) -> io::Result<()> { 1068b8a62b91Sopenharmony_ci let mut affected_keys: u32 = 0; 1069b8a62b91Sopenharmony_ci let mut enabled_keys: u32 = 0; 1070b8a62b91Sopenharmony_ci 1071b8a62b91Sopenharmony_ci for (key, enable) in config { 1072b8a62b91Sopenharmony_ci let key = key.bits(); 1073b8a62b91Sopenharmony_ci affected_keys |= key; 1074b8a62b91Sopenharmony_ci 1075b8a62b91Sopenharmony_ci if enable { 1076b8a62b91Sopenharmony_ci enabled_keys |= key; 1077b8a62b91Sopenharmony_ci } else { 1078b8a62b91Sopenharmony_ci enabled_keys &= !key; 1079b8a62b91Sopenharmony_ci } 1080b8a62b91Sopenharmony_ci } 1081b8a62b91Sopenharmony_ci 1082b8a62b91Sopenharmony_ci if affected_keys == 0 { 1083b8a62b91Sopenharmony_ci return Ok(()); // Nothing to do. 1084b8a62b91Sopenharmony_ci } 1085b8a62b91Sopenharmony_ci 1086b8a62b91Sopenharmony_ci prctl_3args( 1087b8a62b91Sopenharmony_ci PR_PAC_SET_ENABLED_KEYS, 1088b8a62b91Sopenharmony_ci affected_keys as usize as *mut _, 1089b8a62b91Sopenharmony_ci enabled_keys as usize as *mut _, 1090b8a62b91Sopenharmony_ci ) 1091b8a62b91Sopenharmony_ci .map(|_r| ()) 1092b8a62b91Sopenharmony_ci} 1093b8a62b91Sopenharmony_ci 1094b8a62b91Sopenharmony_ci// 1095b8a62b91Sopenharmony_ci// PR_SET_VMA 1096b8a62b91Sopenharmony_ci// 1097b8a62b91Sopenharmony_ci 1098b8a62b91Sopenharmony_ciconst PR_SET_VMA: c_int = 0x53_56_4d_41; 1099b8a62b91Sopenharmony_ci 1100b8a62b91Sopenharmony_ciconst PR_SET_VMA_ANON_NAME: usize = 0; 1101b8a62b91Sopenharmony_ci 1102b8a62b91Sopenharmony_ci/// Set the name for a virtual memory region. 1103b8a62b91Sopenharmony_ci/// 1104b8a62b91Sopenharmony_ci/// # References 1105b8a62b91Sopenharmony_ci/// - [`prctl(PR_SET_VMA,PR_SET_VMA_ANON_NAME,...)`] 1106b8a62b91Sopenharmony_ci/// 1107b8a62b91Sopenharmony_ci/// [`prctl(PR_SET_VMA,PR_SET_VMA_ANON_NAME,...)`]: https://lwn.net/Articles/867818/ 1108b8a62b91Sopenharmony_ci#[inline] 1109b8a62b91Sopenharmony_cipub fn set_virtual_memory_region_name(region: &[u8], name: Option<&CStr>) -> io::Result<()> { 1110b8a62b91Sopenharmony_ci unsafe { 1111b8a62b91Sopenharmony_ci syscalls::prctl( 1112b8a62b91Sopenharmony_ci PR_SET_VMA, 1113b8a62b91Sopenharmony_ci PR_SET_VMA_ANON_NAME as *mut _, 1114b8a62b91Sopenharmony_ci region.as_ptr() as *mut _, 1115b8a62b91Sopenharmony_ci region.len() as *mut _, 1116b8a62b91Sopenharmony_ci name.map_or_else(ptr::null, CStr::as_ptr) as *mut _, 1117b8a62b91Sopenharmony_ci ) 1118b8a62b91Sopenharmony_ci .map(|_r| ()) 1119b8a62b91Sopenharmony_ci } 1120b8a62b91Sopenharmony_ci} 1121