Coverage Report

Created: 2025-11-24 06:55

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