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