//! Bindings for the Linux `prctl` system call. //! //! There are similarities (but also differences) with FreeBSD's `procctl` //! system call, whose interface is located in the `procctl.rs` file.
#![allow(unsafe_code)]
use core::mem::size_of; use core::ptr::{null, null_mut, NonNull};
/// Get the current state of the calling process' `dumpable` attribute. /// /// # References /// - [`prctl(PR_GET_DUMPABLE,...)`] /// /// [`prctl(PR_GET_DUMPABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_GET_DUMPABLE")] pubfn dumpable_behavior() -> io::Result<DumpableBehavior> { unsafe { prctl_1arg(PR_GET_DUMPABLE) }.and_then(TryInto::try_into)
}
const PR_SET_DUMPABLE: c_int = 4;
/// Set the state of the `dumpable` attribute, which determines whether the /// process can be traced and whether core dumps are produced for the calling /// process upon delivery of a signal whose default behavior is to produce a /// core dump. /// /// A similar function with the same name is available on FreeBSD (as part of /// the `procctl` interface), but it has an extra argument which allows to /// select a process other then the current process. /// /// # References /// - [`prctl(PR_SET_DUMPABLE,...)`] /// /// [`prctl(PR_SET_DUMPABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_DUMPABLE")] pubfn set_dumpable_behavior(config: DumpableBehavior) -> io::Result<()> { unsafe { prctl_2args(PR_SET_DUMPABLE, config as usize as *mut _) }.map(|_r| ())
}
// // PR_GET_UNALIGN/PR_SET_UNALIGN //
const PR_GET_UNALIGN: c_int = 5;
bitflags! { /// `PR_UNALIGN_*` flags for use with [`unaligned_access_control`] and /// [`set_unaligned_access_control`]. #[repr(transparent)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pubstruct UnalignedAccessControl: u32 { /// Silently fix up unaligned user accesses. #[doc(alias = "NOPRINT")] #[doc(alias = "PR_UNALIGN_NOPRINT")] const NO_PRINT = 1; /// Generate a [`Signal::Bus`] signal on unaligned user access. #[doc(alias = "PR_UNALIGN_SIGBUS")] const SIGBUS = 2;
/// Use FPEXC for floating point exception enables. const SW_ENABLE = 0x80; /// Floating point divide by zero. const DIV = 0x01_0000; /// Floating point overflow. const OVF = 0x02_0000; /// Floating point underflow. const UND = 0x04_0000; /// Floating point inexact result. const RES = 0x08_0000; /// Floating point invalid operation. const INV = 0x10_0000;
}
}
/// `PR_TIMING_*` values for use with [`timing_method`] and /// [`set_timing_method`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(i32)] pubenum TimingMethod { /// Normal, traditional, statistical process timing.
Statistical = PR_TIMING_STATISTICAL, /// Accurate timestamp based process timing.
TimeStamp = PR_TIMING_TIMESTAMP,
}
impl TryFrom<i32> for TimingMethod { type Error = io::Errno;
/// `PR_ENDIAN_*` values for use with [`endian_mode`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pubenum EndianMode { /// Big endian mode.
Big = PR_ENDIAN_BIG, /// True little endian mode.
Little = PR_ENDIAN_LITTLE, /// `PowerPC` pseudo little endian.
PowerPCLittle = PR_ENDIAN_PPC_LITTLE,
}
impl TryFrom<u32> for EndianMode { type Error = io::Errno;
/// `PR_TSC_*` values for use with [`time_stamp_counter_readability`] and /// [`set_time_stamp_counter_readability`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pubenum TimeStampCounterReadability { /// Allow the use of the timestamp counter.
Readable = PR_TSC_ENABLE, /// Throw a [`Signal::Segv`] signal instead of reading the TSC.
RaiseSIGSEGV = PR_TSC_SIGSEGV,
}
impl TryFrom<u32> for TimeStampCounterReadability { type Error = io::Errno;
/// Get the state of the flag determining if the timestamp counter can be read. /// /// # References /// - [`prctl(PR_GET_TSC,...)`] /// /// [`prctl(PR_GET_TSC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_GET_TSC")] pubfn time_stamp_counter_readability() -> io::Result<TimeStampCounterReadability> { unsafe { prctl_get_at_arg2::<c_uint, _>(PR_GET_TSC) }
}
const PR_SET_TSC: c_int = 26;
/// Set the state of the flag determining if the timestamp counter can be read /// by the process. /// /// # References /// - [`prctl(PR_SET_TSC,...)`] /// /// [`prctl(PR_SET_TSC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_TSC")] pubfn set_time_stamp_counter_readability(
readability: TimeStampCounterReadability,
) -> io::Result<()> { unsafe { prctl_2args(PR_SET_TSC, readability as usize as *mut _) }.map(|_r| ())
}
/// `PR_SET_MM_*` values for use with [`set_virtual_memory_map_address`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pubenum VirtualMemoryMapAddress { /// Set the address above which the program text can run.
CodeStart = PR_SET_MM_START_CODE, /// Set the address below which the program text can run.
CodeEnd = PR_SET_MM_END_CODE, /// Set the address above which initialized and uninitialized (bss) data /// are placed.
DataStart = PR_SET_MM_START_DATA, /// Set the address below which initialized and uninitialized (bss) data /// are placed.
DataEnd = PR_SET_MM_END_DATA, /// Set the start address of the stack.
StackStart = PR_SET_MM_START_STACK, /// Set the address above which the program heap can be expanded with `brk` /// call.
BrkStart = PR_SET_MM_START_BRK, /// Set the current `brk` value.
BrkCurrent = PR_SET_MM_BRK, /// Set the address above which the program command line is placed.
ArgStart = PR_SET_MM_ARG_START, /// Set the address below which the program command line is placed.
ArgEnd = PR_SET_MM_ARG_END, /// Set the address above which the program environment is placed.
EnvironmentStart = PR_SET_MM_ENV_START, /// Set the address below which the program environment is placed.
EnvironmentEnd = PR_SET_MM_ENV_END,
}
/// Modify certain kernel memory map descriptor addresses of the calling /// process. /// /// # References /// - [`prctl(PR_SET_MM,...)`] /// /// # Safety /// /// Please ensure the conditions necessary to safely call this function, as /// detailed in the references above. /// /// [`prctl(PR_SET_MM,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_MM")] pubunsafefn set_virtual_memory_map_address(
option: VirtualMemoryMapAddress,
address: Option<NonNull<c_void>>,
) -> io::Result<()> { let address = address.map_or_else(null_mut, NonNull::as_ptr);
prctl_3args(PR_SET_MM, option as usize as *mut _, address).map(|_r| ())
}
/// Supersede the `/proc/pid/exe` symbolic link with a new one pointing to a /// new executable file. /// /// # References /// - [`prctl(PR_SET_MM,PR_SET_MM_EXE_FILE,...)`] /// /// [`prctl(PR_SET_MM,PR_SET_MM_EXE_FILE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_MM")] #[doc(alias = "PR_SET_MM_EXE_FILE")] pubfn set_executable_file(fd: BorrowedFd<'_>) -> io::Result<()> { let fd = usize::try_from(fd.as_raw_fd()).map_err(|_r| io::Errno::RANGE)?; unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_EXE_FILE as *mut _, fd as *mut _) }.map(|_r| ())
}
/// Set a new auxiliary vector. /// /// # References /// - [`prctl(PR_SET_MM,PR_SET_MM_AUXV,...)`] /// /// # Safety /// /// Please ensure the conditions necessary to safely call this function, as /// detailed in the references above. /// /// [`prctl(PR_SET_MM,PR_SET_MM_AUXV,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_MM")] #[doc(alias = "PR_SET_MM_AUXV")] pubunsafefn set_auxiliary_vector(auxv: &[*const c_void]) -> io::Result<()> {
syscalls::prctl(
PR_SET_MM,
PR_SET_MM_AUXV as *mut _,
auxv.as_ptr() as *mut _,
auxv.len() as *mut _,
null_mut(),
)
.map(|_r| ())
}
/// Get the size of the [`PrctlMmMap`] the kernel expects. /// /// # References /// - [`prctl(PR_SET_MM,PR_SET_MM_MAP_SIZE,...)`] /// /// [`prctl(PR_SET_MM,PR_SET_MM_MAP_SIZE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_MM")] #[doc(alias = "PR_SET_MM_MAP_SIZE")] pubfn virtual_memory_map_config_struct_size() -> io::Result<usize> { letmut value: c_uint = 0; let value_ptr = as_mut_ptr(&mut value); unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_MAP_SIZE as *mut _, value_ptr.cast())? };
Ok(value as usize)
}
/// This structure provides new memory descriptor map which mostly modifies /// `/proc/pid/stat[m]` output for a task. /// This mostly done in a sake of checkpoint/restore functionality. #[repr(C)] #[derive(Debug, Clone)] pubstruct PrctlMmMap { /// Code section start address. pub start_code: u64, /// Code section end address. pub end_code: u64, /// Data section start address. pub start_data: u64, /// Data section end address. pub end_data: u64, /// `brk` start address. pub start_brk: u64, /// `brk` current address. pub brk: u64, /// Stack start address. pub start_stack: u64, /// Program command line start address. pub arg_start: u64, /// Program command line end address. pub arg_end: u64, /// Program environment start address. pub env_start: u64, /// Program environment end address. pub env_end: u64, /// Auxiliary vector start address. pub auxv: *mut u64, /// Auxiliary vector size. pub auxv_size: u32, /// File descriptor of executable file that was used to create this /// process. pub exe_fd: u32,
}
/// Provides one-shot access to all the addresses by passing in a /// [`PrctlMmMap`]. /// /// # References /// - [`prctl(PR_SET_MM,PR_SET_MM_MAP,...)`] /// /// # Safety /// /// Please ensure the conditions necessary to safely call this function, as /// detailed in the references above. /// /// [`prctl(PR_SET_MM,PR_SET_MM_MAP,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_MM")] #[doc(alias = "PR_SET_MM_MAP")] pubunsafefn configure_virtual_memory_map(config: &PrctlMmMap) -> io::Result<()> {
syscalls::prctl(
PR_SET_MM,
PR_SET_MM_MAP as *mut _,
as_ptr(config) as *mut _,
size_of::<PrctlMmMap>() as *mut _,
null_mut(),
)
.map(|_r| ())
}
// // PR_SET_PTRACER //
const PR_SET_PTRACER: c_int = 0x59_61_6d_61;
const PR_SET_PTRACER_ANY: usize = usize::MAX;
/// Process ptracer. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pubenum PTracer { /// None.
None, /// Disable `ptrace` restrictions for the calling process.
Any, /// Specific process.
ProcessID(Pid),
}
/// Declare that the ptracer process can `ptrace` the calling process as if it /// were a direct process ancestor. /// /// # References /// - [`prctl(PR_SET_PTRACER,...)`] /// /// [`prctl(PR_SET_PTRACER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_PTRACER")] pubfn set_ptracer(tracer: PTracer) -> io::Result<()> { let pid = match tracer {
PTracer::None => null_mut(),
PTracer::Any => PR_SET_PTRACER_ANY as *mut _,
PTracer::ProcessID(pid) => pid.as_raw_nonzero().get() as usize as *mut _,
};
/// `PR_SPEC_*` values for use with [`speculative_feature_state`] and /// [`control_speculative_feature`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pubenum SpeculationFeature { /// Set the state of the speculative store bypass misfeature.
SpeculativeStoreBypass = PR_SPEC_STORE_BYPASS, /// Set the state of the indirect branch speculation misfeature.
IndirectBranchSpeculation = PR_SPEC_INDIRECT_BRANCH, /// Flush L1D Cache on context switch out of the task.
FlushL1DCacheOnContextSwitchOutOfTask = PR_SPEC_L1D_FLUSH,
}
impl TryFrom<u32> for SpeculationFeature { type Error = io::Errno;
bitflags! { /// `PR_SPEC_*` flags for use with [`control_speculative_feature`]. #[repr(transparent)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pubstruct SpeculationFeatureControl: u32 { /// The speculation feature is enabled, mitigation is disabled. const ENABLE = 1_u32 << 1; /// The speculation feature is disabled, mitigation is enabled. const DISABLE = 1_u32 << 2; /// The speculation feature is disabled, mitigation is enabled, and it /// cannot be undone. const FORCE_DISABLE = 1_u32 << 3; /// The speculation feature is disabled, mitigation is enabled, and the /// state will be cleared on `execve`. const DISABLE_NOEXEC = 1_u32 << 4;
}
}
bitflags! { /// Zero means the processors are not vulnerable. #[repr(transparent)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pubstruct SpeculationFeatureState: u32 { /// Mitigation can be controlled per thread by /// `PR_SET_SPECULATION_CTRL`. const PRCTL = 1_u32 << 0; /// The speculation feature is enabled, mitigation is disabled. const ENABLE = 1_u32 << 1; /// The speculation feature is disabled, mitigation is enabled. const DISABLE = 1_u32 << 2; /// The speculation feature is disabled, mitigation is enabled, and it /// cannot be undone. const FORCE_DISABLE = 1_u32 << 3; /// The speculation feature is disabled, mitigation is enabled, and the /// state will be cleared on `execve`. const DISABLE_NOEXEC = 1_u32 << 4;
}
}
/// Get the state of the speculation misfeature. /// /// # References /// - [`prctl(PR_GET_SPECULATION_CTRL,...)`] /// /// [`prctl(PR_GET_SPECULATION_CTRL,...)`]: https://www.kernel.org/doc/html/v5.18/userspace-api/spec_ctrl.html #[inline] #[doc(alias = "PR_GET_SPECULATION_CTRL")] pubfn speculative_feature_state(
feature: SpeculationFeature,
) -> io::Result<Option<SpeculationFeatureState>> { let r = unsafe { prctl_2args(PR_GET_SPECULATION_CTRL, feature as usize as *mut _)? } as c_uint;
Ok(SpeculationFeatureState::from_bits(r))
}
const PR_SET_SPECULATION_CTRL: c_int = 53;
/// Sets the state of the speculation misfeature. /// /// # References /// - [`prctl(PR_SET_SPECULATION_CTRL,...)`] /// /// [`prctl(PR_SET_SPECULATION_CTRL,...)`]: https://www.kernel.org/doc/html/v5.18/userspace-api/spec_ctrl.html #[inline] #[doc(alias = "PR_SET_SPECULATION_CTRL")] pubfn control_speculative_feature(
feature: SpeculationFeature,
config: SpeculationFeatureControl,
) -> io::Result<()> { let feature = feature as usize as *mut _; let config = config.bits() as usize as *mut _; unsafe { prctl_3args(PR_SET_SPECULATION_CTRL, feature, config) }.map(|_r| ())
}
// // PR_GET_IO_FLUSHER/PR_SET_IO_FLUSHER //
const PR_GET_IO_FLUSHER: c_int = 58;
/// Get the `IO_FLUSHER` state of the caller. /// /// # References /// - [`prctl(PR_GET_IO_FLUSHER,...)`] /// /// [`prctl(PR_GET_IO_FLUSHER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_GET_IO_FLUSHER")] pubfn is_io_flusher() -> io::Result<bool> { unsafe { prctl_1arg(PR_GET_IO_FLUSHER) }.map(|r| r != 0)
}
const PR_SET_IO_FLUSHER: c_int = 57;
/// Put the process in the `IO_FLUSHER` state, allowing it to make progress /// when allocating memory. /// /// # References /// - [`prctl(PR_SET_IO_FLUSHER,...)`] /// /// [`prctl(PR_SET_IO_FLUSHER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] #[doc(alias = "PR_SET_IO_FLUSHER")] pubfn configure_io_flusher_behavior(enable: bool) -> io::Result<()> { unsafe { prctl_2args(PR_SET_IO_FLUSHER, usize::from(enable) as *mut _) }.map(|_r| ())
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.