1 //! Bindings for the Linux `prctl` system call.
2 //!
3 //! There are similarities (but also differences) with FreeBSD's `procctl`
4 //! system call, whose interface is located in the `procctl.rs` file.
5 
6 #![allow(unsafe_code)]
7 
8 use core::mem::size_of;
9 use core::ptr::{null, null_mut, NonNull};
10 
11 use bitflags::bitflags;
12 
13 use crate::backend::c::{c_int, c_uint, c_void};
14 use crate::backend::prctl::syscalls;
15 use crate::fd::{AsRawFd, BorrowedFd};
16 use crate::ffi::CStr;
17 use crate::io;
18 use crate::prctl::*;
19 use crate::process::{Pid, RawPid};
20 use crate::signal::Signal;
21 use crate::utils::{as_mut_ptr, as_ptr};
22 
23 //
24 // PR_GET_PDEATHSIG/PR_SET_PDEATHSIG
25 //
26 
27 const PR_GET_PDEATHSIG: c_int = 2;
28 
29 /// Get the current value of the parent process death signal.
30 ///
31 /// # References
32 ///  - [Linux: `prctl(PR_GET_PDEATHSIG,...)`]
33 ///  - [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]
34 ///
35 /// [Linux: `prctl(PR_GET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
36 /// [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
37 #[inline]
38 #[doc(alias = "PR_GET_PDEATHSIG")]
parent_process_death_signal() -> io::Result<Option<Signal>>39 pub fn parent_process_death_signal() -> io::Result<Option<Signal>> {
40     unsafe { prctl_get_at_arg2_optional::<c_int>(PR_GET_PDEATHSIG) }.map(Signal::from_raw)
41 }
42 
43 const PR_SET_PDEATHSIG: c_int = 1;
44 
45 /// Set the parent-death signal of the calling process.
46 ///
47 /// # References
48 ///  - [Linux: `prctl(PR_SET_PDEATHSIG,...)`]
49 ///  - [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]
50 ///
51 /// [Linux: `prctl(PR_SET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
52 /// [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
53 #[inline]
54 #[doc(alias = "PR_SET_PDEATHSIG")]
set_parent_process_death_signal(signal: Option<Signal>) -> io::Result<()>55 pub fn set_parent_process_death_signal(signal: Option<Signal>) -> io::Result<()> {
56     let signal = signal.map_or(0_usize, |signal| signal as usize);
57     unsafe { prctl_2args(PR_SET_PDEATHSIG, signal as *mut _) }.map(|_r| ())
58 }
59 
60 //
61 // PR_GET_DUMPABLE/PR_SET_DUMPABLE
62 //
63 
64 const PR_GET_DUMPABLE: c_int = 3;
65 
66 const SUID_DUMP_DISABLE: i32 = 0;
67 const SUID_DUMP_USER: i32 = 1;
68 const SUID_DUMP_ROOT: i32 = 2;
69 
70 /// `SUID_DUMP_*` values for use with [`dumpable_behavior`] and
71 /// [`set_dumpable_behavior`].
72 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
73 #[repr(i32)]
74 pub enum DumpableBehavior {
75     /// Not dumpable.
76     #[doc(alias = "SUID_DUMP_DISABLE")]
77     NotDumpable = SUID_DUMP_DISABLE,
78     /// Dumpable.
79     #[doc(alias = "SUID_DUMP_USER")]
80     Dumpable = SUID_DUMP_USER,
81     /// Dumpable but only readable by root.
82     #[doc(alias = "SUID_DUMP_ROOT")]
83     DumpableReadableOnlyByRoot = SUID_DUMP_ROOT,
84 }
85 
86 impl TryFrom<i32> for DumpableBehavior {
87     type Error = io::Errno;
88 
try_from(value: i32) -> Result<Self, Self::Error>89     fn try_from(value: i32) -> Result<Self, Self::Error> {
90         match value {
91             SUID_DUMP_DISABLE => Ok(Self::NotDumpable),
92             SUID_DUMP_USER => Ok(Self::Dumpable),
93             SUID_DUMP_ROOT => Ok(Self::DumpableReadableOnlyByRoot),
94             _ => Err(io::Errno::RANGE),
95         }
96     }
97 }
98 
99 /// Get the current state of the calling process' `dumpable` attribute.
100 ///
101 /// # References
102 ///  - [`prctl(PR_GET_DUMPABLE,...)`]
103 ///
104 /// [`prctl(PR_GET_DUMPABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
105 #[inline]
106 #[doc(alias = "PR_GET_DUMPABLE")]
dumpable_behavior() -> io::Result<DumpableBehavior>107 pub fn dumpable_behavior() -> io::Result<DumpableBehavior> {
108     unsafe { prctl_1arg(PR_GET_DUMPABLE) }.and_then(TryInto::try_into)
109 }
110 
111 const PR_SET_DUMPABLE: c_int = 4;
112 
113 /// Set the state of the `dumpable` attribute, which determines whether the
114 /// process can be traced and whether core dumps are produced for the calling
115 /// process upon delivery of a signal whose default behavior is to produce a
116 /// core dump.
117 ///
118 /// A similar function with the same name is available on FreeBSD (as part of
119 /// the `procctl` interface), but it has an extra argument which allows to
120 /// select a process other then the current process.
121 ///
122 /// # References
123 ///  - [`prctl(PR_SET_DUMPABLE,...)`]
124 ///
125 /// [`prctl(PR_SET_DUMPABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
126 #[inline]
127 #[doc(alias = "PR_SET_DUMPABLE")]
set_dumpable_behavior(config: DumpableBehavior) -> io::Result<()>128 pub fn set_dumpable_behavior(config: DumpableBehavior) -> io::Result<()> {
129     unsafe { prctl_2args(PR_SET_DUMPABLE, config as usize as *mut _) }.map(|_r| ())
130 }
131 
132 //
133 // PR_GET_UNALIGN/PR_SET_UNALIGN
134 //
135 
136 const PR_GET_UNALIGN: c_int = 5;
137 
138 bitflags! {
139     /// `PR_UNALIGN_*` flags for use with [`unaligned_access_control`] and
140     /// [`set_unaligned_access_control`].
141     #[repr(transparent)]
142     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
143     pub struct UnalignedAccessControl: u32 {
144         /// Silently fix up unaligned user accesses.
145         #[doc(alias = "NOPRINT")]
146         #[doc(alias = "PR_UNALIGN_NOPRINT")]
147         const NO_PRINT = 1;
148         /// Generate a [`Signal::Bus`] signal on unaligned user access.
149         #[doc(alias = "PR_UNALIGN_SIGBUS")]
150         const SIGBUS = 2;
151 
152         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
153         const _ = !0;
154     }
155 }
156 
157 /// Get unaligned access control bits.
158 ///
159 /// # References
160 ///  - [`prctl(PR_GET_UNALIGN,...)`]
161 ///
162 /// [`prctl(PR_GET_UNALIGN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
163 #[inline]
164 #[doc(alias = "PR_GET_UNALIGN")]
unaligned_access_control() -> io::Result<UnalignedAccessControl>165 pub fn unaligned_access_control() -> io::Result<UnalignedAccessControl> {
166     let r = unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_UNALIGN)? };
167     UnalignedAccessControl::from_bits(r).ok_or(io::Errno::RANGE)
168 }
169 
170 const PR_SET_UNALIGN: c_int = 6;
171 
172 /// Set unaligned access control bits.
173 ///
174 /// # References
175 ///  - [`prctl(PR_SET_UNALIGN,...)`]
176 ///
177 /// [`prctl(PR_SET_UNALIGN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
178 #[inline]
179 #[doc(alias = "PR_SET_UNALIGN")]
set_unaligned_access_control(config: UnalignedAccessControl) -> io::Result<()>180 pub fn set_unaligned_access_control(config: UnalignedAccessControl) -> io::Result<()> {
181     unsafe { prctl_2args(PR_SET_UNALIGN, config.bits() as usize as *mut _) }.map(|_r| ())
182 }
183 
184 //
185 // PR_GET_FPEMU/PR_SET_FPEMU
186 //
187 
188 const PR_GET_FPEMU: c_int = 9;
189 
190 bitflags! {
191     /// `PR_FPEMU_*` flags for use with [`floating_point_emulation_control`]
192     /// and [`set_floating_point_emulation_control`].
193     #[repr(transparent)]
194     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
195     pub struct FloatingPointEmulationControl: u32 {
196         /// Silently emulate floating point operations accesses.
197         #[doc(alias = "PR_UNALIGN_NOPRINT")]
198         const NO_PRINT = 1;
199         /// Don't emulate floating point operations, send a [`Signal::Fpe`]
200         /// signal instead.
201         #[doc(alias = "PR_UNALIGN_SIGFPE")]
202         const SIGFPE = 2;
203     }
204 }
205 
206 /// Get floating point emulation control bits.
207 ///
208 /// # References
209 ///  - [`prctl(PR_GET_FPEMU,...)`]
210 ///
211 /// [`prctl(PR_GET_FPEMU,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
212 #[inline]
213 #[doc(alias = "PR_GET_FPEMU")]
floating_point_emulation_control() -> io::Result<FloatingPointEmulationControl>214 pub fn floating_point_emulation_control() -> io::Result<FloatingPointEmulationControl> {
215     let r = unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_FPEMU)? };
216     FloatingPointEmulationControl::from_bits(r).ok_or(io::Errno::RANGE)
217 }
218 
219 const PR_SET_FPEMU: c_int = 10;
220 
221 /// Set floating point emulation control bits.
222 ///
223 /// # References
224 ///  - [`prctl(PR_SET_FPEMU,...)`]
225 ///
226 /// [`prctl(PR_SET_FPEMU,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
227 #[inline]
228 #[doc(alias = "PR_SET_FPEMU")]
set_floating_point_emulation_control( config: FloatingPointEmulationControl, ) -> io::Result<()>229 pub fn set_floating_point_emulation_control(
230     config: FloatingPointEmulationControl,
231 ) -> io::Result<()> {
232     unsafe { prctl_2args(PR_SET_FPEMU, config.bits() as usize as *mut _) }.map(|_r| ())
233 }
234 
235 //
236 // PR_GET_FPEXC/PR_SET_FPEXC
237 //
238 
239 const PR_GET_FPEXC: c_int = 11;
240 
241 bitflags! {
242     /// Zero means floating point exceptions are disabled.
243     #[repr(transparent)]
244     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
245     pub struct FloatingPointExceptionMode: u32 {
246         /// Async non-recoverable exception mode.
247         const NONRECOV = 1;
248         /// Async recoverable exception mode.
249         const ASYNC = 2;
250         /// Precise exception mode.
251         const PRECISE = 3;
252 
253         /// Use FPEXC for floating point exception enables.
254         const SW_ENABLE = 0x80;
255         /// Floating point divide by zero.
256         const DIV = 0x01_0000;
257         /// Floating point overflow.
258         const OVF = 0x02_0000;
259         /// Floating point underflow.
260         const UND = 0x04_0000;
261         /// Floating point inexact result.
262         const RES = 0x08_0000;
263         /// Floating point invalid operation.
264         const INV = 0x10_0000;
265     }
266 }
267 
268 /// Get floating point exception mode.
269 ///
270 /// # References
271 ///  - [`prctl(PR_GET_FPEXC,...)`]
272 ///
273 /// [`prctl(PR_GET_FPEXC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
274 #[inline]
275 #[doc(alias = "PR_GET_FPEXEC")]
floating_point_exception_mode() -> io::Result<Option<FloatingPointExceptionMode>>276 pub fn floating_point_exception_mode() -> io::Result<Option<FloatingPointExceptionMode>> {
277     unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_FPEXC) }
278         .map(FloatingPointExceptionMode::from_bits)
279 }
280 
281 const PR_SET_FPEXC: c_int = 12;
282 
283 /// Set floating point exception mode.
284 ///
285 /// # References
286 ///  - [`prctl(PR_SET_FPEXC,...)`]
287 ///
288 /// [`prctl(PR_SET_FPEXC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
289 #[inline]
290 #[doc(alias = "PR_SET_FPEXEC")]
set_floating_point_exception_mode( config: Option<FloatingPointExceptionMode>, ) -> io::Result<()>291 pub fn set_floating_point_exception_mode(
292     config: Option<FloatingPointExceptionMode>,
293 ) -> io::Result<()> {
294     let config = config.as_ref().map_or(0, FloatingPointExceptionMode::bits);
295     unsafe { prctl_2args(PR_SET_FPEXC, config as usize as *mut _) }.map(|_r| ())
296 }
297 
298 //
299 // PR_GET_TIMING/PR_SET_TIMING
300 //
301 
302 const PR_GET_TIMING: c_int = 13;
303 
304 const PR_TIMING_STATISTICAL: i32 = 0;
305 const PR_TIMING_TIMESTAMP: i32 = 1;
306 
307 /// `PR_TIMING_*` values for use with [`timing_method`] and
308 /// [`set_timing_method`].
309 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
310 #[repr(i32)]
311 pub enum TimingMethod {
312     /// Normal, traditional, statistical process timing.
313     Statistical = PR_TIMING_STATISTICAL,
314     /// Accurate timestamp based process timing.
315     TimeStamp = PR_TIMING_TIMESTAMP,
316 }
317 
318 impl TryFrom<i32> for TimingMethod {
319     type Error = io::Errno;
320 
try_from(value: i32) -> Result<Self, Self::Error>321     fn try_from(value: i32) -> Result<Self, Self::Error> {
322         match value {
323             PR_TIMING_STATISTICAL => Ok(Self::Statistical),
324             PR_TIMING_TIMESTAMP => Ok(Self::TimeStamp),
325             _ => Err(io::Errno::RANGE),
326         }
327     }
328 }
329 
330 /// Get which process timing method is currently in use.
331 ///
332 /// # References
333 ///  - [`prctl(PR_GET_TIMING,...)`]
334 ///
335 /// [`prctl(PR_GET_TIMING,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
336 #[inline]
337 #[doc(alias = "PR_GET_TIMING")]
timing_method() -> io::Result<TimingMethod>338 pub fn timing_method() -> io::Result<TimingMethod> {
339     unsafe { prctl_1arg(PR_GET_TIMING) }.and_then(TryInto::try_into)
340 }
341 
342 const PR_SET_TIMING: c_int = 14;
343 
344 /// Set whether to use (normal, traditional) statistical process timing or
345 /// accurate timestamp-based process timing.
346 ///
347 /// # References
348 ///  - [`prctl(PR_SET_TIMING,...)`]
349 ///
350 /// [`prctl(PR_SET_TIMING,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
351 #[inline]
352 #[doc(alias = "PR_SET_TIMING")]
set_timing_method(method: TimingMethod) -> io::Result<()>353 pub fn set_timing_method(method: TimingMethod) -> io::Result<()> {
354     unsafe { prctl_2args(PR_SET_TIMING, method as usize as *mut _) }.map(|_r| ())
355 }
356 
357 //
358 // PR_GET_ENDIAN/PR_SET_ENDIAN
359 //
360 
361 const PR_GET_ENDIAN: c_int = 19;
362 
363 const PR_ENDIAN_BIG: u32 = 0;
364 const PR_ENDIAN_LITTLE: u32 = 1;
365 const PR_ENDIAN_PPC_LITTLE: u32 = 2;
366 
367 /// `PR_ENDIAN_*` values for use with [`endian_mode`].
368 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
369 #[repr(u32)]
370 pub enum EndianMode {
371     /// Big endian mode.
372     Big = PR_ENDIAN_BIG,
373     /// True little endian mode.
374     Little = PR_ENDIAN_LITTLE,
375     /// `PowerPC` pseudo little endian.
376     PowerPCLittle = PR_ENDIAN_PPC_LITTLE,
377 }
378 
379 impl TryFrom<u32> for EndianMode {
380     type Error = io::Errno;
381 
try_from(value: u32) -> Result<Self, Self::Error>382     fn try_from(value: u32) -> Result<Self, Self::Error> {
383         match value {
384             PR_ENDIAN_BIG => Ok(Self::Big),
385             PR_ENDIAN_LITTLE => Ok(Self::Little),
386             PR_ENDIAN_PPC_LITTLE => Ok(Self::PowerPCLittle),
387             _ => Err(io::Errno::RANGE),
388         }
389     }
390 }
391 
392 /// Get the endianness of the calling process.
393 ///
394 /// # References
395 ///  - [`prctl(PR_GET_ENDIAN,...)`]
396 ///
397 /// [`prctl(PR_GET_ENDIAN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
398 #[inline]
399 #[doc(alias = "PR_GET_ENDIAN")]
endian_mode() -> io::Result<EndianMode>400 pub fn endian_mode() -> io::Result<EndianMode> {
401     unsafe { prctl_get_at_arg2::<c_uint, _>(PR_GET_ENDIAN) }
402 }
403 
404 const PR_SET_ENDIAN: c_int = 20;
405 
406 /// Set the endianness of the calling process.
407 ///
408 /// # References
409 ///  - [`prctl(PR_SET_ENDIAN,...)`]
410 ///
411 /// # Safety
412 ///
413 /// Please ensure the conditions necessary to safely call this function, as
414 /// detailed in the references above.
415 ///
416 /// [`prctl(PR_SET_ENDIAN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
417 #[inline]
418 #[doc(alias = "PR_SET_ENDIAN")]
set_endian_mode(mode: EndianMode) -> io::Result<()>419 pub unsafe fn set_endian_mode(mode: EndianMode) -> io::Result<()> {
420     prctl_2args(PR_SET_ENDIAN, mode as usize as *mut _).map(|_r| ())
421 }
422 
423 //
424 // PR_GET_TSC/PR_SET_TSC
425 //
426 
427 const PR_GET_TSC: c_int = 25;
428 
429 const PR_TSC_ENABLE: u32 = 1;
430 const PR_TSC_SIGSEGV: u32 = 2;
431 
432 /// `PR_TSC_*` values for use with [`time_stamp_counter_readability`] and
433 /// [`set_time_stamp_counter_readability`].
434 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
435 #[repr(u32)]
436 pub enum TimeStampCounterReadability {
437     /// Allow the use of the timestamp counter.
438     Readable = PR_TSC_ENABLE,
439     /// Throw a [`Signal::Segv`] signal instead of reading the TSC.
440     RaiseSIGSEGV = PR_TSC_SIGSEGV,
441 }
442 
443 impl TryFrom<u32> for TimeStampCounterReadability {
444     type Error = io::Errno;
445 
try_from(value: u32) -> Result<Self, Self::Error>446     fn try_from(value: u32) -> Result<Self, Self::Error> {
447         match value {
448             PR_TSC_ENABLE => Ok(Self::Readable),
449             PR_TSC_SIGSEGV => Ok(Self::RaiseSIGSEGV),
450             _ => Err(io::Errno::RANGE),
451         }
452     }
453 }
454 
455 /// Get the state of the flag determining if the timestamp counter can be read.
456 ///
457 /// # References
458 ///  - [`prctl(PR_GET_TSC,...)`]
459 ///
460 /// [`prctl(PR_GET_TSC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
461 #[inline]
462 #[doc(alias = "PR_GET_TSC")]
time_stamp_counter_readability() -> io::Result<TimeStampCounterReadability>463 pub fn time_stamp_counter_readability() -> io::Result<TimeStampCounterReadability> {
464     unsafe { prctl_get_at_arg2::<c_uint, _>(PR_GET_TSC) }
465 }
466 
467 const PR_SET_TSC: c_int = 26;
468 
469 /// Set the state of the flag determining if the timestamp counter can be read
470 /// by the process.
471 ///
472 /// # References
473 ///  - [`prctl(PR_SET_TSC,...)`]
474 ///
475 /// [`prctl(PR_SET_TSC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
476 #[inline]
477 #[doc(alias = "PR_SET_TSC")]
set_time_stamp_counter_readability( readability: TimeStampCounterReadability, ) -> io::Result<()>478 pub fn set_time_stamp_counter_readability(
479     readability: TimeStampCounterReadability,
480 ) -> io::Result<()> {
481     unsafe { prctl_2args(PR_SET_TSC, readability as usize as *mut _) }.map(|_r| ())
482 }
483 
484 //
485 // PR_TASK_PERF_EVENTS_DISABLE/PR_TASK_PERF_EVENTS_ENABLE
486 //
487 
488 const PR_TASK_PERF_EVENTS_DISABLE: c_int = 31;
489 const PR_TASK_PERF_EVENTS_ENABLE: c_int = 32;
490 
491 /// Enable or disable all performance counters attached to the calling process.
492 ///
493 /// # References
494 ///  - [`prctl(PR_TASK_PERF_EVENTS_ENABLE,...)`]
495 ///  - [`prctl(PR_TASK_PERF_EVENTS_DISABLE,...)`]
496 ///
497 /// [`prctl(PR_TASK_PERF_EVENTS_ENABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
498 /// [`prctl(PR_TASK_PERF_EVENTS_DISABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
499 #[inline]
500 #[doc(alias = "PR_TASK_PERF_EVENTS_ENABLE")]
501 #[doc(alias = "PR_TASK_PERF_EVENTS_DISABLE")]
configure_performance_counters(enable: bool) -> io::Result<()>502 pub fn configure_performance_counters(enable: bool) -> io::Result<()> {
503     let option = if enable {
504         PR_TASK_PERF_EVENTS_ENABLE
505     } else {
506         PR_TASK_PERF_EVENTS_DISABLE
507     };
508 
509     unsafe { prctl_1arg(option) }.map(|_r| ())
510 }
511 
512 //
513 // PR_MCE_KILL_GET/PR_MCE_KILL
514 //
515 
516 const PR_MCE_KILL_GET: c_int = 34;
517 
518 const PR_MCE_KILL_LATE: u32 = 0;
519 const PR_MCE_KILL_EARLY: u32 = 1;
520 const PR_MCE_KILL_DEFAULT: u32 = 2;
521 
522 /// `PR_MCE_KILL_*` values for use with
523 /// [`machine_check_memory_corruption_kill_policy`] and
524 /// [`set_machine_check_memory_corruption_kill_policy`].
525 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
526 #[repr(u32)]
527 pub enum MachineCheckMemoryCorruptionKillPolicy {
528     /// Late kill policy.
529     #[doc(alias = "PR_MCE_KILL_LATE")]
530     Late = PR_MCE_KILL_LATE,
531     /// Early kill policy.
532     #[doc(alias = "PR_MCE_KILL_EARLY")]
533     Early = PR_MCE_KILL_EARLY,
534     /// System-wide default policy.
535     #[doc(alias = "PR_MCE_KILL_DEFAULT")]
536     Default = PR_MCE_KILL_DEFAULT,
537 }
538 
539 impl TryFrom<u32> for MachineCheckMemoryCorruptionKillPolicy {
540     type Error = io::Errno;
541 
try_from(value: u32) -> Result<Self, Self::Error>542     fn try_from(value: u32) -> Result<Self, Self::Error> {
543         match value {
544             PR_MCE_KILL_LATE => Ok(Self::Late),
545             PR_MCE_KILL_EARLY => Ok(Self::Early),
546             PR_MCE_KILL_DEFAULT => Ok(Self::Default),
547             _ => Err(io::Errno::RANGE),
548         }
549     }
550 }
551 
552 /// Get the current per-process machine check kill policy.
553 ///
554 /// # References
555 ///  - [`prctl(PR_MCE_KILL_GET,...)`]
556 ///
557 /// [`prctl(PR_MCE_KILL_GET,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
558 #[inline]
559 #[doc(alias = "PR_MCE_KILL_GET")]
machine_check_memory_corruption_kill_policy( ) -> io::Result<MachineCheckMemoryCorruptionKillPolicy>560 pub fn machine_check_memory_corruption_kill_policy(
561 ) -> io::Result<MachineCheckMemoryCorruptionKillPolicy> {
562     let r = unsafe { prctl_1arg(PR_MCE_KILL_GET)? } as c_uint;
563     MachineCheckMemoryCorruptionKillPolicy::try_from(r)
564 }
565 
566 const PR_MCE_KILL: c_int = 33;
567 
568 const PR_MCE_KILL_CLEAR: usize = 0;
569 const PR_MCE_KILL_SET: usize = 1;
570 
571 /// Set the machine check memory corruption kill policy for the calling thread.
572 ///
573 /// # References
574 ///  - [`prctl(PR_MCE_KILL,...)`]
575 ///
576 /// [`prctl(PR_MCE_KILL,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
577 #[inline]
578 #[doc(alias = "PR_MCE_KILL")]
set_machine_check_memory_corruption_kill_policy( policy: Option<MachineCheckMemoryCorruptionKillPolicy>, ) -> io::Result<()>579 pub fn set_machine_check_memory_corruption_kill_policy(
580     policy: Option<MachineCheckMemoryCorruptionKillPolicy>,
581 ) -> io::Result<()> {
582     let (sub_operation, policy) = if let Some(policy) = policy {
583         (PR_MCE_KILL_SET, policy as usize as *mut _)
584     } else {
585         (PR_MCE_KILL_CLEAR, null_mut())
586     };
587 
588     unsafe { prctl_3args(PR_MCE_KILL, sub_operation as *mut _, policy) }.map(|_r| ())
589 }
590 
591 //
592 // PR_SET_MM
593 //
594 
595 const PR_SET_MM: c_int = 35;
596 
597 const PR_SET_MM_START_CODE: u32 = 1;
598 const PR_SET_MM_END_CODE: u32 = 2;
599 const PR_SET_MM_START_DATA: u32 = 3;
600 const PR_SET_MM_END_DATA: u32 = 4;
601 const PR_SET_MM_START_STACK: u32 = 5;
602 const PR_SET_MM_START_BRK: u32 = 6;
603 const PR_SET_MM_BRK: u32 = 7;
604 const PR_SET_MM_ARG_START: u32 = 8;
605 const PR_SET_MM_ARG_END: u32 = 9;
606 const PR_SET_MM_ENV_START: u32 = 10;
607 const PR_SET_MM_ENV_END: u32 = 11;
608 const PR_SET_MM_AUXV: usize = 12;
609 const PR_SET_MM_EXE_FILE: usize = 13;
610 const PR_SET_MM_MAP: usize = 14;
611 const PR_SET_MM_MAP_SIZE: usize = 15;
612 
613 /// `PR_SET_MM_*` values for use with [`set_virtual_memory_map_address`].
614 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
615 #[repr(u32)]
616 pub enum VirtualMemoryMapAddress {
617     /// Set the address above which the program text can run.
618     CodeStart = PR_SET_MM_START_CODE,
619     /// Set the address below which the program text can run.
620     CodeEnd = PR_SET_MM_END_CODE,
621     /// Set the address above which initialized and uninitialized (bss) data
622     /// are placed.
623     DataStart = PR_SET_MM_START_DATA,
624     /// Set the address below which initialized and uninitialized (bss) data
625     /// are placed.
626     DataEnd = PR_SET_MM_END_DATA,
627     /// Set the start address of the stack.
628     StackStart = PR_SET_MM_START_STACK,
629     /// Set the address above which the program heap can be expanded with `brk`
630     /// call.
631     BrkStart = PR_SET_MM_START_BRK,
632     /// Set the current `brk` value.
633     BrkCurrent = PR_SET_MM_BRK,
634     /// Set the address above which the program command line is placed.
635     ArgStart = PR_SET_MM_ARG_START,
636     /// Set the address below which the program command line is placed.
637     ArgEnd = PR_SET_MM_ARG_END,
638     /// Set the address above which the program environment is placed.
639     EnvironmentStart = PR_SET_MM_ENV_START,
640     /// Set the address below which the program environment is placed.
641     EnvironmentEnd = PR_SET_MM_ENV_END,
642 }
643 
644 /// Modify certain kernel memory map descriptor addresses of the calling
645 /// process.
646 ///
647 /// # References
648 ///  - [`prctl(PR_SET_MM,...)`]
649 ///
650 /// # Safety
651 ///
652 /// Please ensure the conditions necessary to safely call this function, as
653 /// detailed in the references above.
654 ///
655 /// [`prctl(PR_SET_MM,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
656 #[inline]
657 #[doc(alias = "PR_SET_MM")]
set_virtual_memory_map_address( option: VirtualMemoryMapAddress, address: Option<NonNull<c_void>>, ) -> io::Result<()>658 pub unsafe fn set_virtual_memory_map_address(
659     option: VirtualMemoryMapAddress,
660     address: Option<NonNull<c_void>>,
661 ) -> io::Result<()> {
662     let address = address.map_or_else(null_mut, NonNull::as_ptr);
663     prctl_3args(PR_SET_MM, option as usize as *mut _, address).map(|_r| ())
664 }
665 
666 /// Supersede the `/proc/pid/exe` symbolic link with a new one pointing to a
667 /// new executable file.
668 ///
669 /// # References
670 ///  - [`prctl(PR_SET_MM,PR_SET_MM_EXE_FILE,...)`]
671 ///
672 /// [`prctl(PR_SET_MM,PR_SET_MM_EXE_FILE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
673 #[inline]
674 #[doc(alias = "PR_SET_MM")]
675 #[doc(alias = "PR_SET_MM_EXE_FILE")]
set_executable_file(fd: BorrowedFd<'_>) -> io::Result<()>676 pub fn set_executable_file(fd: BorrowedFd<'_>) -> io::Result<()> {
677     let fd = usize::try_from(fd.as_raw_fd()).map_err(|_r| io::Errno::RANGE)?;
678     unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_EXE_FILE as *mut _, fd as *mut _) }.map(|_r| ())
679 }
680 
681 /// Set a new auxiliary vector.
682 ///
683 /// # References
684 ///  - [`prctl(PR_SET_MM,PR_SET_MM_AUXV,...)`]
685 ///
686 /// # Safety
687 ///
688 /// Please ensure the conditions necessary to safely call this function, as
689 /// detailed in the references above.
690 ///
691 /// [`prctl(PR_SET_MM,PR_SET_MM_AUXV,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
692 #[inline]
693 #[doc(alias = "PR_SET_MM")]
694 #[doc(alias = "PR_SET_MM_AUXV")]
set_auxiliary_vector(auxv: &[*const c_void]) -> io::Result<()>695 pub unsafe fn set_auxiliary_vector(auxv: &[*const c_void]) -> io::Result<()> {
696     syscalls::prctl(
697         PR_SET_MM,
698         PR_SET_MM_AUXV as *mut _,
699         auxv.as_ptr() as *mut _,
700         auxv.len() as *mut _,
701         null_mut(),
702     )
703     .map(|_r| ())
704 }
705 
706 /// Get the size of the [`PrctlMmMap`] the kernel expects.
707 ///
708 /// # References
709 ///  - [`prctl(PR_SET_MM,PR_SET_MM_MAP_SIZE,...)`]
710 ///
711 /// [`prctl(PR_SET_MM,PR_SET_MM_MAP_SIZE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
712 #[inline]
713 #[doc(alias = "PR_SET_MM")]
714 #[doc(alias = "PR_SET_MM_MAP_SIZE")]
virtual_memory_map_config_struct_size() -> io::Result<usize>715 pub fn virtual_memory_map_config_struct_size() -> io::Result<usize> {
716     let mut value: c_uint = 0;
717     let value_ptr = as_mut_ptr(&mut value);
718     unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_MAP_SIZE as *mut _, value_ptr.cast())? };
719     Ok(value as usize)
720 }
721 
722 /// This structure provides new memory descriptor map which mostly modifies
723 /// `/proc/pid/stat[m]` output for a task.
724 /// This mostly done in a sake of checkpoint/restore functionality.
725 #[repr(C)]
726 #[derive(Debug, Clone)]
727 pub struct PrctlMmMap {
728     /// Code section start address.
729     pub start_code: u64,
730     /// Code section end address.
731     pub end_code: u64,
732     /// Data section start address.
733     pub start_data: u64,
734     /// Data section end address.
735     pub end_data: u64,
736     /// `brk` start address.
737     pub start_brk: u64,
738     /// `brk` current address.
739     pub brk: u64,
740     /// Stack start address.
741     pub start_stack: u64,
742     /// Program command line start address.
743     pub arg_start: u64,
744     /// Program command line end address.
745     pub arg_end: u64,
746     /// Program environment start address.
747     pub env_start: u64,
748     /// Program environment end address.
749     pub env_end: u64,
750     /// Auxiliary vector start address.
751     pub auxv: *mut u64,
752     /// Auxiliary vector size.
753     pub auxv_size: u32,
754     /// File descriptor of executable file that was used to create this
755     /// process.
756     pub exe_fd: u32,
757 }
758 
759 /// Provides one-shot access to all the addresses by passing in a
760 /// [`PrctlMmMap`].
761 ///
762 /// # References
763 ///  - [`prctl(PR_SET_MM,PR_SET_MM_MAP,...)`]
764 ///
765 /// # Safety
766 ///
767 /// Please ensure the conditions necessary to safely call this function, as
768 /// detailed in the references above.
769 ///
770 /// [`prctl(PR_SET_MM,PR_SET_MM_MAP,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
771 #[inline]
772 #[doc(alias = "PR_SET_MM")]
773 #[doc(alias = "PR_SET_MM_MAP")]
configure_virtual_memory_map(config: &PrctlMmMap) -> io::Result<()>774 pub unsafe fn configure_virtual_memory_map(config: &PrctlMmMap) -> io::Result<()> {
775     syscalls::prctl(
776         PR_SET_MM,
777         PR_SET_MM_MAP as *mut _,
778         as_ptr(config) as *mut _,
779         size_of::<PrctlMmMap>() as *mut _,
780         null_mut(),
781     )
782     .map(|_r| ())
783 }
784 
785 //
786 // PR_SET_PTRACER
787 //
788 
789 const PR_SET_PTRACER: c_int = 0x59_61_6d_61;
790 
791 const PR_SET_PTRACER_ANY: usize = usize::MAX;
792 
793 /// Process ptracer.
794 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
795 pub enum PTracer {
796     /// None.
797     None,
798     /// Disable `ptrace` restrictions for the calling process.
799     Any,
800     /// Specific process.
801     ProcessID(Pid),
802 }
803 
804 /// Declare that the ptracer process can `ptrace` the calling process as if it
805 /// were a direct process ancestor.
806 ///
807 /// # References
808 ///  - [`prctl(PR_SET_PTRACER,...)`]
809 ///
810 /// [`prctl(PR_SET_PTRACER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
811 #[inline]
812 #[doc(alias = "PR_SET_PTRACER")]
set_ptracer(tracer: PTracer) -> io::Result<()>813 pub fn set_ptracer(tracer: PTracer) -> io::Result<()> {
814     let pid = match tracer {
815         PTracer::None => null_mut(),
816         PTracer::Any => PR_SET_PTRACER_ANY as *mut _,
817         PTracer::ProcessID(pid) => pid.as_raw_nonzero().get() as usize as *mut _,
818     };
819 
820     unsafe { prctl_2args(PR_SET_PTRACER, pid) }.map(|_r| ())
821 }
822 
823 //
824 // PR_GET_CHILD_SUBREAPER/PR_SET_CHILD_SUBREAPER
825 //
826 
827 const PR_GET_CHILD_SUBREAPER: c_int = 37;
828 
829 /// Get the `child subreaper` setting of the calling process.
830 ///
831 /// # References
832 ///  - [`prctl(PR_GET_CHILD_SUBREAPER,...)`]
833 ///
834 /// [`prctl(PR_GET_CHILD_SUBREAPER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
835 #[inline]
836 #[doc(alias = "PR_GET_CHILD_SUBREAPER")]
child_subreaper() -> io::Result<Option<Pid>>837 pub fn child_subreaper() -> io::Result<Option<Pid>> {
838     unsafe {
839         let r = prctl_get_at_arg2_optional::<c_uint>(PR_GET_CHILD_SUBREAPER)?;
840         Ok(Pid::from_raw(r as RawPid))
841     }
842 }
843 
844 const PR_SET_CHILD_SUBREAPER: c_int = 36;
845 
846 /// Set the `child subreaper` attribute of the calling process.
847 ///
848 /// # References
849 ///  - [`prctl(PR_SET_CHILD_SUBREAPER,...)`]
850 ///
851 /// [`prctl(PR_SET_CHILD_SUBREAPER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
852 #[inline]
853 #[doc(alias = "PR_SET_CHILD_SUBREAPER")]
set_child_subreaper(pid: Option<Pid>) -> io::Result<()>854 pub fn set_child_subreaper(pid: Option<Pid>) -> io::Result<()> {
855     let pid = pid.map_or(0_usize, |pid| pid.as_raw_nonzero().get() as usize);
856     unsafe { prctl_2args(PR_SET_CHILD_SUBREAPER, pid as *mut _) }.map(|_r| ())
857 }
858 
859 //
860 // PR_GET_FP_MODE/PR_SET_FP_MODE
861 //
862 
863 const PR_GET_FP_MODE: c_int = 46;
864 
865 const PR_FP_MODE_FR: u32 = 1_u32 << 0;
866 const PR_FP_MODE_FRE: u32 = 1_u32 << 1;
867 
868 /// `PR_FP_MODE_*` values for use with [`floating_point_mode`] and
869 /// [`set_floating_point_mode`].
870 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
871 #[repr(u32)]
872 pub enum FloatingPointMode {
873     /// 64-bit floating point registers.
874     FloatingPointRegisters = PR_FP_MODE_FR,
875     /// Enable emulation of 32-bit floating-point mode.
876     FloatingPointEmulation = PR_FP_MODE_FRE,
877 }
878 
879 impl TryFrom<u32> for FloatingPointMode {
880     type Error = io::Errno;
881 
try_from(value: u32) -> Result<Self, Self::Error>882     fn try_from(value: u32) -> Result<Self, Self::Error> {
883         match value {
884             PR_FP_MODE_FR => Ok(Self::FloatingPointRegisters),
885             PR_FP_MODE_FRE => Ok(Self::FloatingPointEmulation),
886             _ => Err(io::Errno::RANGE),
887         }
888     }
889 }
890 
891 /// Get the current floating point mode.
892 ///
893 /// # References
894 ///  - [`prctl(PR_GET_FP_MODE,...)`]
895 ///
896 /// [`prctl(PR_GET_FP_MODE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
897 #[inline]
898 #[doc(alias = "PR_GET_FP_MODE")]
floating_point_mode() -> io::Result<FloatingPointMode>899 pub fn floating_point_mode() -> io::Result<FloatingPointMode> {
900     let r = unsafe { prctl_1arg(PR_GET_FP_MODE)? } as c_uint;
901     FloatingPointMode::try_from(r)
902 }
903 
904 const PR_SET_FP_MODE: c_int = 45;
905 
906 /// Allow control of the floating point mode from user space.
907 ///
908 /// # References
909 ///  - [`prctl(PR_SET_FP_MODE,...)`]
910 ///
911 /// [`prctl(PR_SET_FP_MODE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
912 #[inline]
913 #[doc(alias = "PR_SET_FP_MODE")]
set_floating_point_mode(mode: FloatingPointMode) -> io::Result<()>914 pub fn set_floating_point_mode(mode: FloatingPointMode) -> io::Result<()> {
915     unsafe { prctl_2args(PR_SET_FP_MODE, mode as usize as *mut _) }.map(|_r| ())
916 }
917 
918 //
919 // PR_GET_SPECULATION_CTRL/PR_SET_SPECULATION_CTRL
920 //
921 
922 const PR_GET_SPECULATION_CTRL: c_int = 52;
923 
924 const PR_SPEC_STORE_BYPASS: u32 = 0;
925 const PR_SPEC_INDIRECT_BRANCH: u32 = 1;
926 const PR_SPEC_L1D_FLUSH: u32 = 2;
927 
928 /// `PR_SPEC_*` values for use with [`speculative_feature_state`] and
929 /// [`control_speculative_feature`].
930 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
931 #[repr(u32)]
932 pub enum SpeculationFeature {
933     /// Set the state of the speculative store bypass misfeature.
934     SpeculativeStoreBypass = PR_SPEC_STORE_BYPASS,
935     /// Set the state of the indirect branch speculation misfeature.
936     IndirectBranchSpeculation = PR_SPEC_INDIRECT_BRANCH,
937     /// Flush L1D Cache on context switch out of the task.
938     FlushL1DCacheOnContextSwitchOutOfTask = PR_SPEC_L1D_FLUSH,
939 }
940 
941 impl TryFrom<u32> for SpeculationFeature {
942     type Error = io::Errno;
943 
try_from(value: u32) -> Result<Self, Self::Error>944     fn try_from(value: u32) -> Result<Self, Self::Error> {
945         match value {
946             PR_SPEC_STORE_BYPASS => Ok(Self::SpeculativeStoreBypass),
947             PR_SPEC_INDIRECT_BRANCH => Ok(Self::IndirectBranchSpeculation),
948             PR_SPEC_L1D_FLUSH => Ok(Self::FlushL1DCacheOnContextSwitchOutOfTask),
949             _ => Err(io::Errno::RANGE),
950         }
951     }
952 }
953 
954 bitflags! {
955     /// `PR_SPEC_*` flags for use with [`control_speculative_feature`].
956     #[repr(transparent)]
957     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
958     pub struct SpeculationFeatureControl: u32 {
959         /// The speculation feature is enabled, mitigation is disabled.
960         const ENABLE = 1_u32 << 1;
961         /// The speculation feature is disabled, mitigation is enabled.
962         const DISABLE = 1_u32 << 2;
963         /// The speculation feature is disabled, mitigation is enabled, and it
964         /// cannot be undone.
965         const FORCE_DISABLE = 1_u32 << 3;
966         /// The speculation feature is disabled, mitigation is enabled, and the
967         /// state will be cleared on `execve`.
968         const DISABLE_NOEXEC = 1_u32 << 4;
969     }
970 }
971 
972 bitflags! {
973     /// Zero means the processors are not vulnerable.
974     #[repr(transparent)]
975     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
976     pub struct SpeculationFeatureState: u32 {
977         /// Mitigation can be controlled per thread by
978         /// `PR_SET_SPECULATION_CTRL`.
979         const PRCTL = 1_u32 << 0;
980         /// The speculation feature is enabled, mitigation is disabled.
981         const ENABLE = 1_u32 << 1;
982         /// The speculation feature is disabled, mitigation is enabled.
983         const DISABLE = 1_u32 << 2;
984         /// The speculation feature is disabled, mitigation is enabled, and it
985         /// cannot be undone.
986         const FORCE_DISABLE = 1_u32 << 3;
987         /// The speculation feature is disabled, mitigation is enabled, and the
988         /// state will be cleared on `execve`.
989         const DISABLE_NOEXEC = 1_u32 << 4;
990     }
991 }
992 
993 /// Get the state of the speculation misfeature.
994 ///
995 /// # References
996 ///  - [`prctl(PR_GET_SPECULATION_CTRL,...)`]
997 ///
998 /// [`prctl(PR_GET_SPECULATION_CTRL,...)`]: https://www.kernel.org/doc/html/v5.18/userspace-api/spec_ctrl.html
999 #[inline]
1000 #[doc(alias = "PR_GET_SPECULATION_CTRL")]
speculative_feature_state( feature: SpeculationFeature, ) -> io::Result<Option<SpeculationFeatureState>>1001 pub fn speculative_feature_state(
1002     feature: SpeculationFeature,
1003 ) -> io::Result<Option<SpeculationFeatureState>> {
1004     let r = unsafe { prctl_2args(PR_GET_SPECULATION_CTRL, feature as usize as *mut _)? } as c_uint;
1005     Ok(SpeculationFeatureState::from_bits(r))
1006 }
1007 
1008 const PR_SET_SPECULATION_CTRL: c_int = 53;
1009 
1010 /// Sets the state of the speculation misfeature.
1011 ///
1012 /// # References
1013 ///  - [`prctl(PR_SET_SPECULATION_CTRL,...)`]
1014 ///
1015 /// [`prctl(PR_SET_SPECULATION_CTRL,...)`]: https://www.kernel.org/doc/html/v5.18/userspace-api/spec_ctrl.html
1016 #[inline]
1017 #[doc(alias = "PR_SET_SPECULATION_CTRL")]
control_speculative_feature( feature: SpeculationFeature, config: SpeculationFeatureControl, ) -> io::Result<()>1018 pub fn control_speculative_feature(
1019     feature: SpeculationFeature,
1020     config: SpeculationFeatureControl,
1021 ) -> io::Result<()> {
1022     let feature = feature as usize as *mut _;
1023     let config = config.bits() as usize as *mut _;
1024     unsafe { prctl_3args(PR_SET_SPECULATION_CTRL, feature, config) }.map(|_r| ())
1025 }
1026 
1027 //
1028 // PR_GET_IO_FLUSHER/PR_SET_IO_FLUSHER
1029 //
1030 
1031 const PR_GET_IO_FLUSHER: c_int = 58;
1032 
1033 /// Get the `IO_FLUSHER` state of the caller.
1034 ///
1035 /// # References
1036 ///  - [`prctl(PR_GET_IO_FLUSHER,...)`]
1037 ///
1038 /// [`prctl(PR_GET_IO_FLUSHER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
1039 #[inline]
1040 #[doc(alias = "PR_GET_IO_FLUSHER")]
is_io_flusher() -> io::Result<bool>1041 pub fn is_io_flusher() -> io::Result<bool> {
1042     unsafe { prctl_1arg(PR_GET_IO_FLUSHER) }.map(|r| r != 0)
1043 }
1044 
1045 const PR_SET_IO_FLUSHER: c_int = 57;
1046 
1047 /// Put the process in the `IO_FLUSHER` state, allowing it to make progress
1048 /// when allocating memory.
1049 ///
1050 /// # References
1051 ///  - [`prctl(PR_SET_IO_FLUSHER,...)`]
1052 ///
1053 /// [`prctl(PR_SET_IO_FLUSHER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
1054 #[inline]
1055 #[doc(alias = "PR_SET_IO_FLUSHER")]
configure_io_flusher_behavior(enable: bool) -> io::Result<()>1056 pub fn configure_io_flusher_behavior(enable: bool) -> io::Result<()> {
1057     unsafe { prctl_2args(PR_SET_IO_FLUSHER, usize::from(enable) as *mut _) }.map(|_r| ())
1058 }
1059 
1060 //
1061 // PR_PAC_GET_ENABLED_KEYS/PR_PAC_SET_ENABLED_KEYS
1062 //
1063 
1064 const PR_PAC_GET_ENABLED_KEYS: c_int = 61;
1065 
1066 /// Get enabled pointer authentication keys.
1067 ///
1068 /// # References
1069 ///  - [`prctl(PR_PAC_GET_ENABLED_KEYS,...)`]
1070 ///
1071 /// [`prctl(PR_PAC_GET_ENABLED_KEYS,...)`]: https://www.kernel.org/doc/html/v5.18/arm64/pointer-authentication.html
1072 #[inline]
1073 #[doc(alias = "PR_PAC_GET_ENABLED_KEYS")]
enabled_pointer_authentication_keys() -> io::Result<PointerAuthenticationKeys>1074 pub fn enabled_pointer_authentication_keys() -> io::Result<PointerAuthenticationKeys> {
1075     let r = unsafe { prctl_1arg(PR_PAC_GET_ENABLED_KEYS)? } as c_uint;
1076     PointerAuthenticationKeys::from_bits(r).ok_or(io::Errno::RANGE)
1077 }
1078 
1079 const PR_PAC_SET_ENABLED_KEYS: c_int = 60;
1080 
1081 /// Set enabled pointer authentication keys.
1082 ///
1083 /// # References
1084 ///  - [`prctl(PR_PAC_SET_ENABLED_KEYS,...)`]
1085 ///
1086 /// # Safety
1087 ///
1088 /// Please ensure the conditions necessary to safely call this function, as
1089 /// detailed in the references above.
1090 ///
1091 /// [`prctl(PR_PAC_SET_ENABLED_KEYS,...)`]: https://www.kernel.org/doc/html/v5.18/arm64/pointer-authentication.html
1092 #[inline]
1093 #[doc(alias = "PR_PAC_SET_ENABLED_KEYS")]
configure_pointer_authentication_keys( config: impl Iterator<Item = (PointerAuthenticationKeys, bool)>, ) -> io::Result<()>1094 pub unsafe fn configure_pointer_authentication_keys(
1095     config: impl Iterator<Item = (PointerAuthenticationKeys, bool)>,
1096 ) -> io::Result<()> {
1097     let mut affected_keys: u32 = 0;
1098     let mut enabled_keys: u32 = 0;
1099 
1100     for (key, enable) in config {
1101         let key = key.bits();
1102         affected_keys |= key;
1103 
1104         if enable {
1105             enabled_keys |= key;
1106         } else {
1107             enabled_keys &= !key;
1108         }
1109     }
1110 
1111     if affected_keys == 0 {
1112         return Ok(()); // Nothing to do.
1113     }
1114 
1115     prctl_3args(
1116         PR_PAC_SET_ENABLED_KEYS,
1117         affected_keys as usize as *mut _,
1118         enabled_keys as usize as *mut _,
1119     )
1120     .map(|_r| ())
1121 }
1122 
1123 //
1124 // PR_SET_VMA
1125 //
1126 
1127 const PR_SET_VMA: c_int = 0x53_56_4d_41;
1128 
1129 const PR_SET_VMA_ANON_NAME: usize = 0;
1130 
1131 /// Set the name for a virtual memory region.
1132 ///
1133 /// # References
1134 ///  - [`prctl(PR_SET_VMA,PR_SET_VMA_ANON_NAME,...)`]
1135 ///
1136 /// [`prctl(PR_SET_VMA,PR_SET_VMA_ANON_NAME,...)`]: https://lwn.net/Articles/867818/
1137 #[inline]
1138 #[doc(alias = "PR_SET_VMA")]
1139 #[doc(alias = "PR_SET_VMA_ANON_NAME")]
set_virtual_memory_region_name(region: &[u8], name: Option<&CStr>) -> io::Result<()>1140 pub fn set_virtual_memory_region_name(region: &[u8], name: Option<&CStr>) -> io::Result<()> {
1141     unsafe {
1142         syscalls::prctl(
1143             PR_SET_VMA,
1144             PR_SET_VMA_ANON_NAME as *mut _,
1145             region.as_ptr() as *mut _,
1146             region.len() as *mut _,
1147             name.map_or_else(null, CStr::as_ptr) as *mut _,
1148         )
1149         .map(|_r| ())
1150     }
1151 }
1152