summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/process/procctl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/process/procctl.rs')
-rw-r--r--vendor/rustix/src/process/procctl.rs180
1 files changed, 180 insertions, 0 deletions
diff --git a/vendor/rustix/src/process/procctl.rs b/vendor/rustix/src/process/procctl.rs
new file mode 100644
index 000000000..ff842513f
--- /dev/null
+++ b/vendor/rustix/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))
+ }
+ }
+}