]> git.proxmox.com Git - rustc.git/blob - vendor/rustix-0.36.5/src/process/procctl.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / vendor / rustix-0.36.5 / src / process / procctl.rs
1 //! Bindings for the FreeBSD `procctl` system call.
2 //!
3 //! There are similarities (but also differences) with Linux's `prctl` system call, whose interface
4 //! is located in the `prctl.rs` file.
5
6 #![allow(unsafe_code)]
7
8 use core::mem::MaybeUninit;
9
10 use crate::backend::c::{c_int, c_uint, c_void};
11 use crate::backend::process::syscalls;
12 use crate::backend::process::types::{RawId, Signal};
13 use crate::io;
14 use crate::process::{Pid, RawPid};
15
16 //
17 // Helper functions.
18 //
19
20 /// Subset of `idtype_t` C enum, with only the values allowed by `procctl`.
21 #[repr(i32)]
22 pub enum IdType {
23 /// Process id.
24 Pid = 0,
25 /// Process group id.
26 Pgid = 2,
27 }
28
29 /// A process selector for use with the `procctl` interface.
30 ///
31 /// `None` represents the current process. `Some((IdType::Pid, pid))` represents the process
32 /// with pid `pid`. `Some((IdType::Pgid, pgid))` represents the control processes belonging to
33 /// the process group with id `pgid`.
34 pub type ProcSelector = Option<(IdType, Pid)>;
35 fn proc_selector_to_raw(selector: ProcSelector) -> (IdType, RawPid) {
36 match selector {
37 Some((idtype, id)) => (idtype, id.as_raw_nonzero().get()),
38 None => (IdType::Pid, 0),
39 }
40 }
41
42 #[inline]
43 pub(crate) unsafe fn procctl(
44 option: c_int,
45 process: ProcSelector,
46 data: *mut c_void,
47 ) -> io::Result<()> {
48 let (idtype, id) = proc_selector_to_raw(process);
49 syscalls::procctl(idtype as c_uint, id as RawId, option, data)
50 }
51
52 #[inline]
53 pub(crate) unsafe fn procctl_set<P>(
54 option: c_int,
55 process: ProcSelector,
56 data: &P,
57 ) -> io::Result<()> {
58 procctl(option, process, (data as *const P as *mut P).cast())
59 }
60
61 #[inline]
62 pub(crate) unsafe fn procctl_get_optional<P>(
63 option: c_int,
64 process: ProcSelector,
65 ) -> io::Result<P> {
66 let mut value: MaybeUninit<P> = MaybeUninit::uninit();
67 procctl(option, process, value.as_mut_ptr().cast())?;
68 Ok(value.assume_init())
69 }
70
71 //
72 // PROC_PDEATHSIG_STATUS/PROC_PDEATHSIG_CTL
73 //
74
75 const PROC_PDEATHSIG_STATUS: c_int = 12;
76
77 /// Get the current value of the parent process death signal.
78 ///
79 /// # References
80 /// - [Linux: `prctl(PR_GET_PDEATHSIG,...)`]
81 /// - [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]
82 ///
83 /// [Linux: `prctl(PR_GET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
84 /// [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
85 #[inline]
86 pub fn parent_process_death_signal() -> io::Result<Option<Signal>> {
87 unsafe { procctl_get_optional::<c_int>(PROC_PDEATHSIG_STATUS, None) }.map(Signal::from_raw)
88 }
89
90 const PROC_PDEATHSIG_CTL: c_int = 11;
91
92 /// Set the parent-death signal of the calling process.
93 ///
94 /// # References
95 /// - [Linux: `prctl(PR_SET_PDEATHSIG,...)`]
96 /// - [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]
97 ///
98 /// [Linux: `prctl(PR_SET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
99 /// [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
100 #[inline]
101 pub fn set_parent_process_death_signal(signal: Option<Signal>) -> io::Result<()> {
102 let signal = signal.map_or(0, |signal| signal as c_int);
103 unsafe { procctl_set::<c_int>(PROC_PDEATHSIG_CTL, None, &signal) }
104 }
105
106 //
107 // PROC_TRACE_CTL
108 //
109
110 const PROC_TRACE_CTL: c_int = 7;
111
112 const PROC_TRACE_CTL_ENABLE: i32 = 1;
113 const PROC_TRACE_CTL_DISABLE: i32 = 2;
114 const PROC_TRACE_CTL_DISABLE_EXEC: i32 = 3;
115
116 /// `PROC_TRACE_CTL_*`.
117 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
118 #[repr(i32)]
119 pub enum DumpableBehavior {
120 /// Not dumpable.
121 NotDumpable = PROC_TRACE_CTL_DISABLE,
122 /// Dumpable.
123 Dumpable = PROC_TRACE_CTL_ENABLE,
124 /// Not dumpable, and this behaviour is preserved across `execve` calls.
125 NotDumpableExecPreserved = PROC_TRACE_CTL_DISABLE_EXEC,
126 }
127
128 /// Set the state of the `dumpable` attribute for the process indicated by `idtype` and `id`.
129 /// This determines whether the process can be traced and whether core dumps are produced for
130 /// the process upon delivery of a signal whose default behavior is to produce a core dump.
131 ///
132 /// This is similar to `set_dumpable_behavior` on Linux, with the exception that on FreeBSD
133 /// there is an extra argument `process`. When `process` is set to `None`, the operation is
134 /// performed for the current process, like on Linux.
135 ///
136 /// # References
137 /// - [`procctl(PROC_TRACE_CTL,...)`]
138 ///
139 /// [`procctl(PROC_TRACE_CTL,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
140 #[inline]
141 pub fn set_dumpable_behavior(process: ProcSelector, config: DumpableBehavior) -> io::Result<()> {
142 unsafe { procctl(PROC_TRACE_CTL, process, config as usize as *mut _) }
143 }
144
145 //
146 // PROC_TRACE_STATUS
147 //
148
149 const PROC_TRACE_STATUS: c_int = 8;
150
151 /// Tracing status as returned by [`trace_status`].
152 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
153 pub enum TracingStatus {
154 /// Tracing is disabled for the process.
155 NotTraceble,
156 /// Tracing is not disabled for the process, but not debugger/tracer is attached.
157 Tracable,
158 /// The process is being traced by the process whose pid is stored in the first
159 /// component of this variant.
160 BeingTraced(Pid),
161 }
162
163 /// Get the tracing status of the process indicated by `idtype` and `id`.
164 ///
165 /// # References
166 /// - [`procctl(PROC_TRACE_STATUS,...)`]
167 ///
168 /// [`procctl(PROC_TRACE_STATUS,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
169 #[inline]
170 pub fn trace_status(process: ProcSelector) -> io::Result<TracingStatus> {
171 let val = unsafe { procctl_get_optional::<c_int>(PROC_TRACE_STATUS, process) }?;
172 match val {
173 -1 => Ok(TracingStatus::NotTraceble),
174 0 => Ok(TracingStatus::Tracable),
175 pid => {
176 let pid = unsafe { Pid::from_raw(pid as RawPid) }.ok_or(io::Errno::RANGE)?;
177 Ok(TracingStatus::BeingTraced(pid))
178 }
179 }
180 }