diff options
Diffstat (limited to 'vendor/rustix-0.36.5/src/process/procctl.rs')
-rw-r--r-- | vendor/rustix-0.36.5/src/process/procctl.rs | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/vendor/rustix-0.36.5/src/process/procctl.rs b/vendor/rustix-0.36.5/src/process/procctl.rs new file mode 100644 index 000000000..ff842513f --- /dev/null +++ b/vendor/rustix-0.36.5/src/process/procctl.rs @@ -0,0 +1,180 @@ +//! Bindings for the FreeBSD `procctl` system call. +//! +//! There are similarities (but also differences) with Linux's `prctl` system call, whose interface +//! is located in the `prctl.rs` file. + +#![allow(unsafe_code)] + +use core::mem::MaybeUninit; + +use crate::backend::c::{c_int, c_uint, c_void}; +use crate::backend::process::syscalls; +use crate::backend::process::types::{RawId, Signal}; +use crate::io; +use crate::process::{Pid, RawPid}; + +// +// Helper functions. +// + +/// Subset of `idtype_t` C enum, with only the values allowed by `procctl`. +#[repr(i32)] +pub enum IdType { + /// Process id. + Pid = 0, + /// Process group id. + Pgid = 2, +} + +/// A process selector for use with the `procctl` interface. +/// +/// `None` represents the current process. `Some((IdType::Pid, pid))` represents the process +/// with pid `pid`. `Some((IdType::Pgid, pgid))` represents the control processes belonging to +/// the process group with id `pgid`. +pub type ProcSelector = Option<(IdType, Pid)>; +fn proc_selector_to_raw(selector: ProcSelector) -> (IdType, RawPid) { + match selector { + Some((idtype, id)) => (idtype, id.as_raw_nonzero().get()), + None => (IdType::Pid, 0), + } +} + +#[inline] +pub(crate) unsafe fn procctl( + option: c_int, + process: ProcSelector, + data: *mut c_void, +) -> io::Result<()> { + let (idtype, id) = proc_selector_to_raw(process); + syscalls::procctl(idtype as c_uint, id as RawId, option, data) +} + +#[inline] +pub(crate) unsafe fn procctl_set<P>( + option: c_int, + process: ProcSelector, + data: &P, +) -> io::Result<()> { + procctl(option, process, (data as *const P as *mut P).cast()) +} + +#[inline] +pub(crate) unsafe fn procctl_get_optional<P>( + option: c_int, + process: ProcSelector, +) -> io::Result<P> { + let mut value: MaybeUninit<P> = MaybeUninit::uninit(); + procctl(option, process, value.as_mut_ptr().cast())?; + Ok(value.assume_init()) +} + +// +// PROC_PDEATHSIG_STATUS/PROC_PDEATHSIG_CTL +// + +const PROC_PDEATHSIG_STATUS: c_int = 12; + +/// Get the current value of the parent process death signal. +/// +/// # References +/// - [Linux: `prctl(PR_GET_PDEATHSIG,...)`] +/// - [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`] +/// +/// [Linux: `prctl(PR_GET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html +/// [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 +#[inline] +pub fn parent_process_death_signal() -> io::Result<Option<Signal>> { + unsafe { procctl_get_optional::<c_int>(PROC_PDEATHSIG_STATUS, None) }.map(Signal::from_raw) +} + +const PROC_PDEATHSIG_CTL: c_int = 11; + +/// Set the parent-death signal of the calling process. +/// +/// # References +/// - [Linux: `prctl(PR_SET_PDEATHSIG,...)`] +/// - [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`] +/// +/// [Linux: `prctl(PR_SET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html +/// [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 +#[inline] +pub fn set_parent_process_death_signal(signal: Option<Signal>) -> io::Result<()> { + let signal = signal.map_or(0, |signal| signal as c_int); + unsafe { procctl_set::<c_int>(PROC_PDEATHSIG_CTL, None, &signal) } +} + +// +// PROC_TRACE_CTL +// + +const PROC_TRACE_CTL: c_int = 7; + +const PROC_TRACE_CTL_ENABLE: i32 = 1; +const PROC_TRACE_CTL_DISABLE: i32 = 2; +const PROC_TRACE_CTL_DISABLE_EXEC: i32 = 3; + +/// `PROC_TRACE_CTL_*`. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[repr(i32)] +pub enum DumpableBehavior { + /// Not dumpable. + NotDumpable = PROC_TRACE_CTL_DISABLE, + /// Dumpable. + Dumpable = PROC_TRACE_CTL_ENABLE, + /// Not dumpable, and this behaviour is preserved across `execve` calls. + NotDumpableExecPreserved = PROC_TRACE_CTL_DISABLE_EXEC, +} + +/// Set the state of the `dumpable` attribute for the process indicated by `idtype` and `id`. +/// This determines whether the process can be traced and whether core dumps are produced for +/// the process upon delivery of a signal whose default behavior is to produce a core dump. +/// +/// This is similar to `set_dumpable_behavior` on Linux, with the exception that on FreeBSD +/// there is an extra argument `process`. When `process` is set to `None`, the operation is +/// performed for the current process, like on Linux. +/// +/// # References +/// - [`procctl(PROC_TRACE_CTL,...)`] +/// +/// [`procctl(PROC_TRACE_CTL,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 +#[inline] +pub fn set_dumpable_behavior(process: ProcSelector, config: DumpableBehavior) -> io::Result<()> { + unsafe { procctl(PROC_TRACE_CTL, process, config as usize as *mut _) } +} + +// +// PROC_TRACE_STATUS +// + +const PROC_TRACE_STATUS: c_int = 8; + +/// Tracing status as returned by [`trace_status`]. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum TracingStatus { + /// Tracing is disabled for the process. + NotTraceble, + /// Tracing is not disabled for the process, but not debugger/tracer is attached. + Tracable, + /// The process is being traced by the process whose pid is stored in the first + /// component of this variant. + BeingTraced(Pid), +} + +/// Get the tracing status of the process indicated by `idtype` and `id`. +/// +/// # References +/// - [`procctl(PROC_TRACE_STATUS,...)`] +/// +/// [`procctl(PROC_TRACE_STATUS,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 +#[inline] +pub fn trace_status(process: ProcSelector) -> io::Result<TracingStatus> { + let val = unsafe { procctl_get_optional::<c_int>(PROC_TRACE_STATUS, process) }?; + match val { + -1 => Ok(TracingStatus::NotTraceble), + 0 => Ok(TracingStatus::Tracable), + pid => { + let pid = unsafe { Pid::from_raw(pid as RawPid) }.ok_or(io::Errno::RANGE)?; + Ok(TracingStatus::BeingTraced(pid)) + } + } +} |