diff options
Diffstat (limited to 'vendor/rustix/src/process/procctl.rs')
-rw-r--r-- | vendor/rustix/src/process/procctl.rs | 530 |
1 files changed, 0 insertions, 530 deletions
diff --git a/vendor/rustix/src/process/procctl.rs b/vendor/rustix/src/process/procctl.rs deleted file mode 100644 index bb63722..0000000 --- a/vendor/rustix/src/process/procctl.rs +++ /dev/null @@ -1,530 +0,0 @@ -//! 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)] - -#[cfg(feature = "alloc")] -use alloc::{vec, vec::Vec}; -use core::mem::MaybeUninit; -use core::ptr; - -use bitflags::bitflags; - -use crate::backend::c::{c_int, c_uint, c_void}; -use crate::backend::process::syscalls; -use crate::backend::process::types::RawId; -use crate::io; -use crate::process::{Pid, RawPid}; -use crate::signal::Signal; -use crate::utils::{as_mut_ptr, as_ptr}; - -// -// 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, (as_ptr(data) 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://man.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://man.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 -/// - [FreeBSD `procctl(PROC_TRACE_CTL,...)`] -/// -/// [FreeBSD `procctl(PROC_TRACE_CTL,...)`]: https://man.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 -/// - [FreeBSD `procctl(PROC_TRACE_STATUS,...)`] -/// -/// [FreeBSD `procctl(PROC_TRACE_STATUS,...)`]: https://man.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 = Pid::from_raw(pid as RawPid).ok_or(io::Errno::RANGE)?; - Ok(TracingStatus::BeingTraced(pid)) - } - } -} - -// -// PROC_REAP_* -// - -const PROC_REAP_ACQUIRE: c_int = 2; -const PROC_REAP_RELEASE: c_int = 3; - -/// Acquire or release the reaper status of the calling process. -/// -/// # References -/// - [FreeBSD: `procctl(PROC_REAP_ACQUIRE/RELEASE,...)`] -/// -/// [FreeBSD: `procctl(PROC_REAP_ACQUIRE/RELEASE,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 -#[inline] -pub fn set_reaper_status(reaper: bool) -> io::Result<()> { - unsafe { - procctl( - if reaper { - PROC_REAP_ACQUIRE - } else { - PROC_REAP_RELEASE - }, - None, - ptr::null_mut(), - ) - } -} - -const PROC_REAP_STATUS: c_int = 4; - -bitflags! { - /// `REAPER_STATUS_*`. - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct ReaperStatusFlags: c_uint { - /// The process has acquired reaper status. - const OWNED = 1; - /// The process is the root of the reaper tree (pid 1). - const REALINIT = 2; - - /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> - const _ = !0; - } -} - -#[repr(C)] -struct procctl_reaper_status { - rs_flags: c_uint, - rs_children: c_uint, - rs_descendants: c_uint, - rs_reaper: RawPid, - rs_pid: RawPid, - rs_pad0: [c_uint; 15], -} - -/// Reaper status as returned by [`get_reaper_status`]. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct ReaperStatus { - /// The flags. - pub flags: ReaperStatusFlags, - /// The number of children of the reaper among the descendants. - pub children: usize, - /// The total number of descendants of the reaper(s), not counting - /// descendants of the reaper in the subtree. - pub descendants: usize, - /// The pid of the reaper for the specified process id. - pub reaper: Pid, - /// The pid of one reaper child if there are any descendants. - pub pid: Option<Pid>, -} - -/// Get information about the reaper of the specified process (or the process -/// itself if it is a reaper). -/// -/// # References -/// - [FreeBSD: `procctl(PROC_REAP_STATUS,...)`] -/// -/// [FreeBSD: `procctl(PROC_REAP_STATUS,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 -#[inline] -pub fn get_reaper_status(process: ProcSelector) -> io::Result<ReaperStatus> { - let raw = unsafe { procctl_get_optional::<procctl_reaper_status>(PROC_REAP_STATUS, process) }?; - Ok(ReaperStatus { - flags: ReaperStatusFlags::from_bits_retain(raw.rs_flags), - children: raw.rs_children as _, - descendants: raw.rs_descendants as _, - reaper: Pid::from_raw(raw.rs_reaper).ok_or(io::Errno::RANGE)?, - pid: if raw.rs_pid == -1 { - None - } else { - Some(Pid::from_raw(raw.rs_pid).ok_or(io::Errno::RANGE)?) - }, - }) -} - -const PROC_REAP_GETPIDS: c_int = 5; - -bitflags! { - /// `REAPER_PIDINFO_*`. - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - pub struct PidInfoFlags: c_uint { - /// This structure was filled by the kernel. - const VALID = 1; - /// The pid field identifies a direct child of the reaper. - const CHILD = 2; - /// The reported process is itself a reaper. Descendants of a - /// subordinate reaper are not reported. - const REAPER = 4; - /// The reported process is in the zombie state. - const ZOMBIE = 8; - /// The reported process is stopped by - /// [`Signal::Stop`]/[`Signal::Tstp`]. - const STOPPED = 16; - /// The reported process is in the process of exiting. - const EXITING = 32; - } -} - -#[repr(C)] -#[derive(Default, Clone)] -struct procctl_reaper_pidinfo { - pi_pid: RawPid, - pi_subtree: RawPid, - pi_flags: c_uint, - pi_pad0: [c_uint; 15], -} - -#[repr(C)] -struct procctl_reaper_pids { - rp_count: c_uint, - rp_pad0: [c_uint; 15], - rp_pids: *mut procctl_reaper_pidinfo, -} - -/// A child process of a reaper. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct PidInfo { - /// The flags of the process. - pub flags: PidInfoFlags, - /// The pid of the process. - pub pid: Pid, - /// The pid of the child of the reaper which is the (grand-..)parent of the - /// process. - pub subtree: Pid, -} - -/// Get the list of descendants of the specified reaper process. -/// -/// # References -/// - [FreeBSD: `procctl(PROC_REAP_GETPIDS,...)`] -/// -/// [FreeBSD: `procctl(PROC_REAP_GETPIDS,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 -#[cfg(feature = "alloc")] -pub fn get_reaper_pids(process: ProcSelector) -> io::Result<Vec<PidInfo>> { - // Sadly no better way to guarantee that we get all the results than to - // allocate ~8MB of memory.. - const PID_MAX: usize = 99999; - let mut pids: Vec<procctl_reaper_pidinfo> = vec![Default::default(); PID_MAX]; - let mut pinfo = procctl_reaper_pids { - rp_count: PID_MAX as _, - rp_pad0: [0; 15], - rp_pids: pids.as_mut_slice().as_mut_ptr(), - }; - unsafe { procctl(PROC_REAP_GETPIDS, process, as_mut_ptr(&mut pinfo).cast())? }; - let mut result = Vec::new(); - for raw in pids.into_iter() { - let flags = PidInfoFlags::from_bits_retain(raw.pi_flags); - if !flags.contains(PidInfoFlags::VALID) { - break; - } - result.push(PidInfo { - flags, - subtree: Pid::from_raw(raw.pi_subtree).ok_or(io::Errno::RANGE)?, - pid: Pid::from_raw(raw.pi_pid).ok_or(io::Errno::RANGE)?, - }); - } - Ok(result) -} - -const PROC_REAP_KILL: c_int = 6; - -bitflags! { - /// `REAPER_KILL_*`. - #[repr(transparent)] - #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] - struct KillFlags: c_uint { - const CHILDREN = 1; - const SUBTREE = 2; - } -} - -#[repr(C)] -struct procctl_reaper_kill { - rk_sig: c_int, - rk_flags: c_uint, - rk_subtree: RawPid, - rk_killed: c_uint, - rk_fpid: RawPid, - rk_pad0: [c_uint; 15], -} - -/// Reaper status as returned by [`get_reaper_status`]. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct KillResult { - /// The number of processes that were signalled. - pub killed: usize, - /// The pid of the first process that wasn't successfully signalled. - pub first_failed: Option<Pid>, -} - -/// Deliver a signal to some subset of -/// -/// # References -/// - [FreeBSD: `procctl(PROC_REAP_KILL,...)`] -/// -/// [FreeBSD: `procctl(PROC_REAP_KILL,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 -pub fn reaper_kill( - process: ProcSelector, - signal: Signal, - direct_children: bool, - subtree: Option<Pid>, -) -> io::Result<KillResult> { - let mut flags = KillFlags::empty(); - flags.set(KillFlags::CHILDREN, direct_children); - flags.set(KillFlags::SUBTREE, subtree.is_some()); - let mut req = procctl_reaper_kill { - rk_sig: signal as c_int, - rk_flags: flags.bits(), - rk_subtree: subtree.map(|p| p.as_raw_nonzero().into()).unwrap_or(0), - rk_killed: 0, - rk_fpid: 0, - rk_pad0: [0; 15], - }; - unsafe { procctl(PROC_REAP_KILL, process, as_mut_ptr(&mut req).cast())? }; - Ok(KillResult { - killed: req.rk_killed as _, - first_failed: Pid::from_raw(req.rk_fpid), - }) -} - -// -// PROC_TRAPCAP_STATUS/PROC_TRAPCAP_CTL -// - -const PROC_TRAPCAP_CTL: c_int = 9; - -const PROC_TRAPCAP_CTL_ENABLE: i32 = 1; -const PROC_TRAPCAP_CTL_DISABLE: i32 = 2; - -/// `PROC_TRAPCAP_CTL_*`. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[repr(i32)] -pub enum TrapCapBehavior { - /// Disable the [`Signal::Trap`] signal delivery on capability mode access - /// violations. - Disable = PROC_TRAPCAP_CTL_DISABLE, - /// Enable the [`Signal::Trap`] signal delivery on capability mode access - /// violations. - Enable = PROC_TRAPCAP_CTL_ENABLE, -} - -/// Set the current value of the capability mode violation trapping behavior. -/// If this behavior is enabled, the kernel would deliver a [`Signal::Trap`] -/// signal on any return from a system call that would result in a -/// [`io::Errno::NOTCAPABLE`]` or [`io::Errno::CAPMODE`] error. -/// -/// This behavior is inherited by the children of the process and is kept -/// across `execve` calls. -/// -/// # References -/// - [FreeBSD: `procctl(PROC_TRAPCAP_CTL,...)`] -/// -/// [FreeBSD: `procctl(PROC_TRAPCAP_CTL,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 -#[inline] -pub fn set_trap_cap_behavior(process: ProcSelector, config: TrapCapBehavior) -> io::Result<()> { - let config = config as c_int; - unsafe { procctl_set::<c_int>(PROC_TRAPCAP_CTL, process, &config) } -} - -const PROC_TRAPCAP_STATUS: c_int = 10; - -/// Get the current value of the capability mode violation trapping behavior. -/// -/// # References -/// - [FreeBSD: `procctl(PROC_TRAPCAP_STATUS,...)`] -/// -/// [FreeBSD: `procctl(PROC_TRAPCAP_STATUS,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 -#[inline] -pub fn trap_cap_behavior(process: ProcSelector) -> io::Result<TrapCapBehavior> { - let val = unsafe { procctl_get_optional::<c_int>(PROC_TRAPCAP_STATUS, process) }?; - match val { - PROC_TRAPCAP_CTL_DISABLE => Ok(TrapCapBehavior::Disable), - PROC_TRAPCAP_CTL_ENABLE => Ok(TrapCapBehavior::Enable), - _ => Err(io::Errno::RANGE), - } -} - -// -// PROC_NO_NEW_PRIVS_STATUS/PROC_NO_NEW_PRIVS_CTL -// - -const PROC_NO_NEW_PRIVS_CTL: c_int = 19; - -const PROC_NO_NEW_PRIVS_ENABLE: c_int = 1; - -/// Enable the `no_new_privs` mode that ignores SUID and SGID bits on `execve` -/// in the specified process and its future descendants. -/// -/// This is similar to `set_no_new_privs` on Linux, with the exception that on -/// FreeBSD there is no argument `no_new_privs` argument as it's only possible -/// to enable this mode and there's no going back. -/// -/// # References -/// - [Linux: `prctl(PR_SET_NO_NEW_PRIVS,...)`] -/// - [FreeBSD: `procctl(PROC_NO_NEW_PRIVS_CTL,...)`] -/// -/// [Linux: `prctl(PR_SET_NO_NEW_PRIVS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html -/// [FreeBSD: `procctl(PROC_NO_NEW_PRIVS_CTL,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 -#[inline] -pub fn set_no_new_privs(process: ProcSelector) -> io::Result<()> { - unsafe { procctl_set::<c_int>(PROC_NO_NEW_PRIVS_CTL, process, &PROC_NO_NEW_PRIVS_ENABLE) } -} - -const PROC_NO_NEW_PRIVS_STATUS: c_int = 20; - -/// Check the `no_new_privs` mode of the specified process. -/// -/// # References -/// - [Linux: `prctl(PR_GET_NO_NEW_PRIVS,...)`] -/// - [FreeBSD: `procctl(PROC_NO_NEW_PRIVS_STATUS,...)`] -/// -/// [Linux: `prctl(PR_GET_NO_NEW_PRIVS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html -/// [FreeBSD: `procctl(PROC_NO_NEW_PRIVS_STATUS,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 -#[inline] -pub fn no_new_privs(process: ProcSelector) -> io::Result<bool> { - unsafe { procctl_get_optional::<c_int>(PROC_NO_NEW_PRIVS_STATUS, process) } - .map(|x| x == PROC_NO_NEW_PRIVS_ENABLE) -} |