1#![allow(unsafe_code)]
7
8use core::mem::size_of;
9use core::num::NonZeroI32;
10use core::ptr::{null, null_mut, NonNull};
11
12use bitflags::bitflags;
13
14use crate::backend::prctl::syscalls;
15use crate::fd::{AsRawFd as _, BorrowedFd, RawFd};
16use crate::ffi::{c_int, c_uint, c_void, CStr};
17use crate::io;
18use crate::prctl::*;
19use crate::process::{Pid, RawPid};
20use crate::signal::Signal;
21use crate::utils::{as_mut_ptr, as_ptr};
22
23const PR_GET_PDEATHSIG: c_int = 2;
28
29#[inline]
38#[doc(alias = "PR_GET_PDEATHSIG")]
39pub fn parent_process_death_signal() -> io::Result<Option<Signal>> {
40 let raw = unsafe { prctl_get_at_arg2_optional::<c_int>(PR_GET_PDEATHSIG)? };
41 if let Some(non_zero) = NonZeroI32::new(raw) {
42 Ok(Some(unsafe {
47 Signal::from_raw_nonzero_unchecked(non_zero)
48 }))
49 } else {
50 Ok(None)
51 }
52}
53
54const PR_SET_PDEATHSIG: c_int = 1;
55
56#[inline]
65#[doc(alias = "PR_SET_PDEATHSIG")]
66pub fn set_parent_process_death_signal(signal: Option<Signal>) -> io::Result<()> {
67 let signal = signal.map_or(0_usize, |signal| signal.as_raw() as usize);
68 unsafe { prctl_2args(PR_SET_PDEATHSIG, signal as *mut _) }.map(|_r| ())
69}
70
71const PR_GET_DUMPABLE: c_int = 3;
76
77const SUID_DUMP_DISABLE: i32 = 0;
78const SUID_DUMP_USER: i32 = 1;
79const SUID_DUMP_ROOT: i32 = 2;
80
81#[derive(Copy, Clone, Debug, Eq, PartialEq)]
84#[repr(i32)]
85pub enum DumpableBehavior {
86 #[doc(alias = "SUID_DUMP_DISABLE")]
88 NotDumpable = SUID_DUMP_DISABLE,
89 #[doc(alias = "SUID_DUMP_USER")]
91 Dumpable = SUID_DUMP_USER,
92 #[doc(alias = "SUID_DUMP_ROOT")]
94 DumpableReadableOnlyByRoot = SUID_DUMP_ROOT,
95}
96
97impl TryFrom<i32> for DumpableBehavior {
98 type Error = io::Errno;
99
100 fn try_from(value: i32) -> Result<Self, Self::Error> {
101 match value {
102 SUID_DUMP_DISABLE => Ok(Self::NotDumpable),
103 SUID_DUMP_USER => Ok(Self::Dumpable),
104 SUID_DUMP_ROOT => Ok(Self::DumpableReadableOnlyByRoot),
105 _ => Err(io::Errno::RANGE),
106 }
107 }
108}
109
110#[inline]
117#[doc(alias = "PR_GET_DUMPABLE")]
118pub fn dumpable_behavior() -> io::Result<DumpableBehavior> {
119 unsafe { prctl_1arg(PR_GET_DUMPABLE) }.and_then(TryInto::try_into)
120}
121
122const PR_SET_DUMPABLE: c_int = 4;
123
124#[inline]
139#[doc(alias = "PR_SET_DUMPABLE")]
140pub fn set_dumpable_behavior(config: DumpableBehavior) -> io::Result<()> {
141 unsafe { prctl_2args(PR_SET_DUMPABLE, config as usize as *mut _) }.map(|_r| ())
142}
143
144const PR_GET_UNALIGN: c_int = 5;
149
150bitflags! {
151 #[repr(transparent)]
154 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
155 pub struct UnalignedAccessControl: u32 {
156 #[doc(alias = "NOPRINT")]
158 #[doc(alias = "PR_UNALIGN_NOPRINT")]
159 const NO_PRINT = 1;
160 #[doc(alias = "PR_UNALIGN_SIGBUS")]
162 const SIGBUS = 2;
163
164 const _ = !0;
166 }
167}
168
169#[inline]
176#[doc(alias = "PR_GET_UNALIGN")]
177pub fn unaligned_access_control() -> io::Result<UnalignedAccessControl> {
178 let r = unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_UNALIGN)? };
179 UnalignedAccessControl::from_bits(r).ok_or(io::Errno::RANGE)
180}
181
182const PR_SET_UNALIGN: c_int = 6;
183
184#[inline]
191#[doc(alias = "PR_SET_UNALIGN")]
192pub fn set_unaligned_access_control(config: UnalignedAccessControl) -> io::Result<()> {
193 unsafe { prctl_2args(PR_SET_UNALIGN, config.bits() as usize as *mut _) }.map(|_r| ())
194}
195
196const PR_GET_FPEMU: c_int = 9;
201
202bitflags! {
203 #[repr(transparent)]
206 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
207 pub struct FloatingPointEmulationControl: u32 {
208 #[doc(alias = "PR_UNALIGN_NOPRINT")]
210 const NO_PRINT = 1;
211 #[doc(alias = "PR_UNALIGN_SIGFPE")]
214 const SIGFPE = 2;
215 }
216}
217
218#[inline]
225#[doc(alias = "PR_GET_FPEMU")]
226pub fn floating_point_emulation_control() -> io::Result<FloatingPointEmulationControl> {
227 let r = unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_FPEMU)? };
228 FloatingPointEmulationControl::from_bits(r).ok_or(io::Errno::RANGE)
229}
230
231const PR_SET_FPEMU: c_int = 10;
232
233#[inline]
240#[doc(alias = "PR_SET_FPEMU")]
241pub fn set_floating_point_emulation_control(
242 config: FloatingPointEmulationControl,
243) -> io::Result<()> {
244 unsafe { prctl_2args(PR_SET_FPEMU, config.bits() as usize as *mut _) }.map(|_r| ())
245}
246
247const PR_GET_FPEXC: c_int = 11;
252
253bitflags! {
254 #[repr(transparent)]
256 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
257 pub struct FloatingPointExceptionMode: u32 {
258 const NONRECOV = 1;
260 const ASYNC = 2;
262 const PRECISE = 3;
264
265 const SW_ENABLE = 0x80;
267 const DIV = 0x01_0000;
269 const OVF = 0x02_0000;
271 const UND = 0x04_0000;
273 const RES = 0x08_0000;
275 const INV = 0x10_0000;
277 }
278}
279
280#[inline]
287#[doc(alias = "PR_GET_FPEXEC")]
288pub fn floating_point_exception_mode() -> io::Result<Option<FloatingPointExceptionMode>> {
289 unsafe { prctl_get_at_arg2_optional::<c_uint>(PR_GET_FPEXC) }
290 .map(FloatingPointExceptionMode::from_bits)
291}
292
293const PR_SET_FPEXC: c_int = 12;
294
295#[inline]
302#[doc(alias = "PR_SET_FPEXEC")]
303pub fn set_floating_point_exception_mode(
304 config: Option<FloatingPointExceptionMode>,
305) -> io::Result<()> {
306 let config = config.as_ref().map_or(0, FloatingPointExceptionMode::bits);
307 unsafe { prctl_2args(PR_SET_FPEXC, config as usize as *mut _) }.map(|_r| ())
308}
309
310const PR_GET_TIMING: c_int = 13;
315
316const PR_TIMING_STATISTICAL: i32 = 0;
317const PR_TIMING_TIMESTAMP: i32 = 1;
318
319#[derive(Copy, Clone, Debug, Eq, PartialEq)]
322#[repr(i32)]
323pub enum TimingMethod {
324 Statistical = PR_TIMING_STATISTICAL,
326 TimeStamp = PR_TIMING_TIMESTAMP,
328}
329
330impl TryFrom<i32> for TimingMethod {
331 type Error = io::Errno;
332
333 fn try_from(value: i32) -> Result<Self, Self::Error> {
334 match value {
335 PR_TIMING_STATISTICAL => Ok(Self::Statistical),
336 PR_TIMING_TIMESTAMP => Ok(Self::TimeStamp),
337 _ => Err(io::Errno::RANGE),
338 }
339 }
340}
341
342#[inline]
349#[doc(alias = "PR_GET_TIMING")]
350pub fn timing_method() -> io::Result<TimingMethod> {
351 unsafe { prctl_1arg(PR_GET_TIMING) }.and_then(TryInto::try_into)
352}
353
354const PR_SET_TIMING: c_int = 14;
355
356#[inline]
364#[doc(alias = "PR_SET_TIMING")]
365pub fn set_timing_method(method: TimingMethod) -> io::Result<()> {
366 unsafe { prctl_2args(PR_SET_TIMING, method as usize as *mut _) }.map(|_r| ())
367}
368
369const PR_GET_ENDIAN: c_int = 19;
374
375const PR_ENDIAN_BIG: u32 = 0;
376const PR_ENDIAN_LITTLE: u32 = 1;
377const PR_ENDIAN_PPC_LITTLE: u32 = 2;
378
379#[derive(Copy, Clone, Debug, Eq, PartialEq)]
381#[repr(u32)]
382pub enum EndianMode {
383 Big = PR_ENDIAN_BIG,
385 Little = PR_ENDIAN_LITTLE,
387 PowerPCLittle = PR_ENDIAN_PPC_LITTLE,
389}
390
391impl TryFrom<u32> for EndianMode {
392 type Error = io::Errno;
393
394 fn try_from(value: u32) -> Result<Self, Self::Error> {
395 match value {
396 PR_ENDIAN_BIG => Ok(Self::Big),
397 PR_ENDIAN_LITTLE => Ok(Self::Little),
398 PR_ENDIAN_PPC_LITTLE => Ok(Self::PowerPCLittle),
399 _ => Err(io::Errno::RANGE),
400 }
401 }
402}
403
404#[inline]
411#[doc(alias = "PR_GET_ENDIAN")]
412pub fn endian_mode() -> io::Result<EndianMode> {
413 unsafe { prctl_get_at_arg2::<c_uint, _>(PR_GET_ENDIAN) }
414}
415
416const PR_SET_ENDIAN: c_int = 20;
417
418#[inline]
430#[doc(alias = "PR_SET_ENDIAN")]
431pub unsafe fn set_endian_mode(mode: EndianMode) -> io::Result<()> {
432 prctl_2args(PR_SET_ENDIAN, mode as usize as *mut _).map(|_r| ())
433}
434
435const PR_GET_TSC: c_int = 25;
440
441const PR_TSC_ENABLE: u32 = 1;
442const PR_TSC_SIGSEGV: u32 = 2;
443
444#[derive(Copy, Clone, Debug, Eq, PartialEq)]
447#[repr(u32)]
448pub enum TimeStampCounterReadability {
449 Readable = PR_TSC_ENABLE,
451 RaiseSIGSEGV = PR_TSC_SIGSEGV,
453}
454
455impl TryFrom<u32> for TimeStampCounterReadability {
456 type Error = io::Errno;
457
458 fn try_from(value: u32) -> Result<Self, Self::Error> {
459 match value {
460 PR_TSC_ENABLE => Ok(Self::Readable),
461 PR_TSC_SIGSEGV => Ok(Self::RaiseSIGSEGV),
462 _ => Err(io::Errno::RANGE),
463 }
464 }
465}
466
467#[inline]
474#[doc(alias = "PR_GET_TSC")]
475pub fn time_stamp_counter_readability() -> io::Result<TimeStampCounterReadability> {
476 unsafe { prctl_get_at_arg2::<c_uint, _>(PR_GET_TSC) }
477}
478
479const PR_SET_TSC: c_int = 26;
480
481#[inline]
489#[doc(alias = "PR_SET_TSC")]
490pub fn set_time_stamp_counter_readability(
491 readability: TimeStampCounterReadability,
492) -> io::Result<()> {
493 unsafe { prctl_2args(PR_SET_TSC, readability as usize as *mut _) }.map(|_r| ())
494}
495
496const PR_TASK_PERF_EVENTS_DISABLE: c_int = 31;
501const PR_TASK_PERF_EVENTS_ENABLE: c_int = 32;
502
503#[inline]
512#[doc(alias = "PR_TASK_PERF_EVENTS_ENABLE")]
513#[doc(alias = "PR_TASK_PERF_EVENTS_DISABLE")]
514pub fn configure_performance_counters(enable: bool) -> io::Result<()> {
515 let option = if enable {
516 PR_TASK_PERF_EVENTS_ENABLE
517 } else {
518 PR_TASK_PERF_EVENTS_DISABLE
519 };
520
521 unsafe { prctl_1arg(option) }.map(|_r| ())
522}
523
524const PR_MCE_KILL_GET: c_int = 34;
529
530const PR_MCE_KILL_LATE: u32 = 0;
531const PR_MCE_KILL_EARLY: u32 = 1;
532const PR_MCE_KILL_DEFAULT: u32 = 2;
533
534#[derive(Copy, Clone, Debug, Eq, PartialEq)]
538#[repr(u32)]
539pub enum MachineCheckMemoryCorruptionKillPolicy {
540 #[doc(alias = "PR_MCE_KILL_LATE")]
542 Late = PR_MCE_KILL_LATE,
543 #[doc(alias = "PR_MCE_KILL_EARLY")]
545 Early = PR_MCE_KILL_EARLY,
546 #[doc(alias = "PR_MCE_KILL_DEFAULT")]
548 Default = PR_MCE_KILL_DEFAULT,
549}
550
551impl TryFrom<u32> for MachineCheckMemoryCorruptionKillPolicy {
552 type Error = io::Errno;
553
554 fn try_from(value: u32) -> Result<Self, Self::Error> {
555 match value {
556 PR_MCE_KILL_LATE => Ok(Self::Late),
557 PR_MCE_KILL_EARLY => Ok(Self::Early),
558 PR_MCE_KILL_DEFAULT => Ok(Self::Default),
559 _ => Err(io::Errno::RANGE),
560 }
561 }
562}
563
564#[inline]
571#[doc(alias = "PR_MCE_KILL_GET")]
572pub fn machine_check_memory_corruption_kill_policy(
573) -> io::Result<MachineCheckMemoryCorruptionKillPolicy> {
574 let r = unsafe { prctl_1arg(PR_MCE_KILL_GET)? } as c_uint;
575 MachineCheckMemoryCorruptionKillPolicy::try_from(r)
576}
577
578const PR_MCE_KILL: c_int = 33;
579
580const PR_MCE_KILL_CLEAR: usize = 0;
581const PR_MCE_KILL_SET: usize = 1;
582
583#[inline]
590#[doc(alias = "PR_MCE_KILL")]
591pub fn set_machine_check_memory_corruption_kill_policy(
592 policy: Option<MachineCheckMemoryCorruptionKillPolicy>,
593) -> io::Result<()> {
594 let (sub_operation, policy) = if let Some(policy) = policy {
595 (PR_MCE_KILL_SET, policy as usize as *mut _)
596 } else {
597 (PR_MCE_KILL_CLEAR, null_mut())
598 };
599
600 unsafe { prctl_3args(PR_MCE_KILL, sub_operation as *mut _, policy) }.map(|_r| ())
601}
602
603const PR_SET_MM: c_int = 35;
608
609const PR_SET_MM_START_CODE: u32 = 1;
610const PR_SET_MM_END_CODE: u32 = 2;
611const PR_SET_MM_START_DATA: u32 = 3;
612const PR_SET_MM_END_DATA: u32 = 4;
613const PR_SET_MM_START_STACK: u32 = 5;
614const PR_SET_MM_START_BRK: u32 = 6;
615const PR_SET_MM_BRK: u32 = 7;
616const PR_SET_MM_ARG_START: u32 = 8;
617const PR_SET_MM_ARG_END: u32 = 9;
618const PR_SET_MM_ENV_START: u32 = 10;
619const PR_SET_MM_ENV_END: u32 = 11;
620const PR_SET_MM_AUXV: usize = 12;
621const PR_SET_MM_EXE_FILE: usize = 13;
622const PR_SET_MM_MAP: usize = 14;
623const PR_SET_MM_MAP_SIZE: usize = 15;
624
625#[derive(Copy, Clone, Debug, Eq, PartialEq)]
627#[repr(u32)]
628pub enum VirtualMemoryMapAddress {
629 CodeStart = PR_SET_MM_START_CODE,
631 CodeEnd = PR_SET_MM_END_CODE,
633 DataStart = PR_SET_MM_START_DATA,
636 DataEnd = PR_SET_MM_END_DATA,
639 StackStart = PR_SET_MM_START_STACK,
641 BrkStart = PR_SET_MM_START_BRK,
644 BrkCurrent = PR_SET_MM_BRK,
646 ArgStart = PR_SET_MM_ARG_START,
648 ArgEnd = PR_SET_MM_ARG_END,
650 EnvironmentStart = PR_SET_MM_ENV_START,
652 EnvironmentEnd = PR_SET_MM_ENV_END,
654}
655
656#[inline]
669#[doc(alias = "PR_SET_MM")]
670pub unsafe fn set_virtual_memory_map_address(
671 option: VirtualMemoryMapAddress,
672 address: Option<NonNull<c_void>>,
673) -> io::Result<()> {
674 let address = address.map_or_else(null_mut, NonNull::as_ptr);
675 prctl_3args(PR_SET_MM, option as usize as *mut _, address).map(|_r| ())
676}
677
678#[inline]
686#[doc(alias = "PR_SET_MM")]
687#[doc(alias = "PR_SET_MM_EXE_FILE")]
688pub fn set_executable_file(fd: BorrowedFd<'_>) -> io::Result<()> {
689 let fd = usize::try_from(fd.as_raw_fd()).map_err(|_r| io::Errno::RANGE)?;
690 unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_EXE_FILE as *mut _, fd as *mut _) }.map(|_r| ())
691}
692
693#[inline]
705#[doc(alias = "PR_SET_MM")]
706#[doc(alias = "PR_SET_MM_AUXV")]
707pub unsafe fn set_auxiliary_vector(auxv: &[*const c_void]) -> io::Result<()> {
708 syscalls::prctl(
709 PR_SET_MM,
710 PR_SET_MM_AUXV as *mut _,
711 auxv.as_ptr() as *mut _,
712 auxv.len() as *mut _,
713 null_mut(),
714 )
715 .map(|_r| ())
716}
717
718#[inline]
725#[doc(alias = "PR_SET_MM")]
726#[doc(alias = "PR_SET_MM_MAP_SIZE")]
727pub fn virtual_memory_map_config_struct_size() -> io::Result<usize> {
728 let mut value: c_uint = 0;
729 let value_ptr = as_mut_ptr(&mut value);
730 unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_MAP_SIZE as *mut _, value_ptr.cast())? };
731 Ok(value as usize)
732}
733
734#[repr(C)]
738#[derive(Debug, Clone)]
739pub struct PrctlMmMap {
740 pub start_code: u64,
742 pub end_code: u64,
744 pub start_data: u64,
746 pub end_data: u64,
748 pub start_brk: u64,
750 pub brk: u64,
752 pub start_stack: u64,
754 pub arg_start: u64,
756 pub arg_end: u64,
758 pub env_start: u64,
760 pub env_end: u64,
762 pub auxv: *mut u64,
764 pub auxv_size: u32,
766 pub exe_fd: RawFd,
769}
770
771#[inline]
784#[doc(alias = "PR_SET_MM")]
785#[doc(alias = "PR_SET_MM_MAP")]
786pub unsafe fn configure_virtual_memory_map(config: &PrctlMmMap) -> io::Result<()> {
787 syscalls::prctl(
788 PR_SET_MM,
789 PR_SET_MM_MAP as *mut _,
790 as_ptr(config) as *mut _,
791 size_of::<PrctlMmMap>() as *mut _,
792 null_mut(),
793 )
794 .map(|_r| ())
795}
796
797const PR_SET_PTRACER: c_int = 0x59_61_6d_61;
802
803const PR_SET_PTRACER_ANY: usize = usize::MAX;
804
805#[derive(Copy, Clone, Debug, Eq, PartialEq)]
807pub enum PTracer {
808 None,
810 Any,
812 ProcessID(Pid),
814}
815
816#[inline]
824#[doc(alias = "PR_SET_PTRACER")]
825pub fn set_ptracer(tracer: PTracer) -> io::Result<()> {
826 let pid = match tracer {
827 PTracer::None => null_mut(),
828 PTracer::Any => PR_SET_PTRACER_ANY as *mut _,
829 PTracer::ProcessID(pid) => pid.as_raw_nonzero().get() as usize as *mut _,
830 };
831
832 unsafe { prctl_2args(PR_SET_PTRACER, pid) }.map(|_r| ())
833}
834
835const PR_GET_CHILD_SUBREAPER: c_int = 37;
840
841#[inline]
848#[doc(alias = "PR_GET_CHILD_SUBREAPER")]
849pub fn child_subreaper() -> io::Result<Option<Pid>> {
850 unsafe {
851 let r = prctl_get_at_arg2_optional::<c_uint>(PR_GET_CHILD_SUBREAPER)?;
852 Ok(Pid::from_raw(r as RawPid))
853 }
854}
855
856const PR_SET_CHILD_SUBREAPER: c_int = 36;
857
858#[inline]
865#[doc(alias = "PR_SET_CHILD_SUBREAPER")]
866pub fn set_child_subreaper(pid: Option<Pid>) -> io::Result<()> {
867 let pid = pid.map_or(0_usize, |pid| pid.as_raw_nonzero().get() as usize);
868 unsafe { prctl_2args(PR_SET_CHILD_SUBREAPER, pid as *mut _) }.map(|_r| ())
869}
870
871const PR_GET_FP_MODE: c_int = 46;
876
877const PR_FP_MODE_FR: u32 = 1_u32 << 0;
878const PR_FP_MODE_FRE: u32 = 1_u32 << 1;
879
880#[derive(Copy, Clone, Debug, Eq, PartialEq)]
883#[repr(u32)]
884pub enum FloatingPointMode {
885 FloatingPointRegisters = PR_FP_MODE_FR,
887 FloatingPointEmulation = PR_FP_MODE_FRE,
889}
890
891impl TryFrom<u32> for FloatingPointMode {
892 type Error = io::Errno;
893
894 fn try_from(value: u32) -> Result<Self, Self::Error> {
895 match value {
896 PR_FP_MODE_FR => Ok(Self::FloatingPointRegisters),
897 PR_FP_MODE_FRE => Ok(Self::FloatingPointEmulation),
898 _ => Err(io::Errno::RANGE),
899 }
900 }
901}
902
903#[inline]
910#[doc(alias = "PR_GET_FP_MODE")]
911pub fn floating_point_mode() -> io::Result<FloatingPointMode> {
912 let r = unsafe { prctl_1arg(PR_GET_FP_MODE)? } as c_uint;
913 FloatingPointMode::try_from(r)
914}
915
916const PR_SET_FP_MODE: c_int = 45;
917
918#[inline]
925#[doc(alias = "PR_SET_FP_MODE")]
926pub fn set_floating_point_mode(mode: FloatingPointMode) -> io::Result<()> {
927 unsafe { prctl_2args(PR_SET_FP_MODE, mode as usize as *mut _) }.map(|_r| ())
928}
929
930const PR_GET_SPECULATION_CTRL: c_int = 52;
935
936const PR_SPEC_STORE_BYPASS: u32 = 0;
937const PR_SPEC_INDIRECT_BRANCH: u32 = 1;
938const PR_SPEC_L1D_FLUSH: u32 = 2;
939
940#[derive(Copy, Clone, Debug, Eq, PartialEq)]
943#[repr(u32)]
944pub enum SpeculationFeature {
945 SpeculativeStoreBypass = PR_SPEC_STORE_BYPASS,
947 IndirectBranchSpeculation = PR_SPEC_INDIRECT_BRANCH,
949 FlushL1DCacheOnContextSwitchOutOfTask = PR_SPEC_L1D_FLUSH,
951}
952
953impl TryFrom<u32> for SpeculationFeature {
954 type Error = io::Errno;
955
956 fn try_from(value: u32) -> Result<Self, Self::Error> {
957 match value {
958 PR_SPEC_STORE_BYPASS => Ok(Self::SpeculativeStoreBypass),
959 PR_SPEC_INDIRECT_BRANCH => Ok(Self::IndirectBranchSpeculation),
960 PR_SPEC_L1D_FLUSH => Ok(Self::FlushL1DCacheOnContextSwitchOutOfTask),
961 _ => Err(io::Errno::RANGE),
962 }
963 }
964}
965
966bitflags! {
967 #[repr(transparent)]
969 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
970 pub struct SpeculationFeatureControl: u32 {
971 const ENABLE = 1_u32 << 1;
973 const DISABLE = 1_u32 << 2;
975 const FORCE_DISABLE = 1_u32 << 3;
978 const DISABLE_NOEXEC = 1_u32 << 4;
981 }
982}
983
984bitflags! {
985 #[repr(transparent)]
987 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
988 pub struct SpeculationFeatureState: u32 {
989 const PRCTL = 1_u32 << 0;
992 const ENABLE = 1_u32 << 1;
994 const DISABLE = 1_u32 << 2;
996 const FORCE_DISABLE = 1_u32 << 3;
999 const DISABLE_NOEXEC = 1_u32 << 4;
1002 }
1003}
1004
1005#[inline]
1012#[doc(alias = "PR_GET_SPECULATION_CTRL")]
1013pub fn speculative_feature_state(
1014 feature: SpeculationFeature,
1015) -> io::Result<Option<SpeculationFeatureState>> {
1016 let r = unsafe { prctl_2args(PR_GET_SPECULATION_CTRL, feature as usize as *mut _)? } as c_uint;
1017 Ok(SpeculationFeatureState::from_bits(r))
1018}
1019
1020const PR_SET_SPECULATION_CTRL: c_int = 53;
1021
1022#[inline]
1029#[doc(alias = "PR_SET_SPECULATION_CTRL")]
1030pub fn control_speculative_feature(
1031 feature: SpeculationFeature,
1032 config: SpeculationFeatureControl,
1033) -> io::Result<()> {
1034 let feature = feature as usize as *mut _;
1035 let config = config.bits() as usize as *mut _;
1036 unsafe { prctl_3args(PR_SET_SPECULATION_CTRL, feature, config) }.map(|_r| ())
1037}
1038
1039const PR_GET_IO_FLUSHER: c_int = 58;
1044
1045#[inline]
1052#[doc(alias = "PR_GET_IO_FLUSHER")]
1053pub fn is_io_flusher() -> io::Result<bool> {
1054 unsafe { prctl_1arg(PR_GET_IO_FLUSHER) }.map(|r| r != 0)
1055}
1056
1057const PR_SET_IO_FLUSHER: c_int = 57;
1058
1059#[inline]
1067#[doc(alias = "PR_SET_IO_FLUSHER")]
1068pub fn configure_io_flusher_behavior(enable: bool) -> io::Result<()> {
1069 unsafe { prctl_2args(PR_SET_IO_FLUSHER, usize::from(enable) as *mut _) }.map(|_r| ())
1070}
1071
1072const PR_PAC_GET_ENABLED_KEYS: c_int = 61;
1077
1078#[inline]
1085#[doc(alias = "PR_PAC_GET_ENABLED_KEYS")]
1086pub fn enabled_pointer_authentication_keys() -> io::Result<PointerAuthenticationKeys> {
1087 let r = unsafe { prctl_1arg(PR_PAC_GET_ENABLED_KEYS)? } as c_uint;
1088 PointerAuthenticationKeys::from_bits(r).ok_or(io::Errno::RANGE)
1089}
1090
1091const PR_PAC_SET_ENABLED_KEYS: c_int = 60;
1092
1093#[inline]
1105#[doc(alias = "PR_PAC_SET_ENABLED_KEYS")]
1106pub unsafe fn configure_pointer_authentication_keys<
1107 Config: Iterator<Item = (PointerAuthenticationKeys, bool)>,
1108>(
1109 config: Config,
1110) -> io::Result<()> {
1111 let mut affected_keys: u32 = 0;
1112 let mut enabled_keys: u32 = 0;
1113
1114 for (key, enable) in config {
1115 let key = key.bits();
1116 affected_keys |= key;
1117
1118 if enable {
1119 enabled_keys |= key;
1120 } else {
1121 enabled_keys &= !key;
1122 }
1123 }
1124
1125 if affected_keys == 0 {
1126 return Ok(()); }
1128
1129 prctl_3args(
1130 PR_PAC_SET_ENABLED_KEYS,
1131 affected_keys as usize as *mut _,
1132 enabled_keys as usize as *mut _,
1133 )
1134 .map(|_r| ())
1135}
1136
1137const PR_SET_VMA: c_int = 0x53_56_4d_41;
1142
1143const PR_SET_VMA_ANON_NAME: usize = 0;
1144
1145#[inline]
1152#[doc(alias = "PR_SET_VMA")]
1153#[doc(alias = "PR_SET_VMA_ANON_NAME")]
1154pub fn set_virtual_memory_region_name(region: &[u8], name: Option<&CStr>) -> io::Result<()> {
1155 unsafe {
1156 syscalls::prctl(
1157 PR_SET_VMA,
1158 PR_SET_VMA_ANON_NAME as *mut _,
1159 region.as_ptr() as *mut _,
1160 region.len() as *mut _,
1161 name.map_or_else(null, CStr::as_ptr) as *mut _,
1162 )
1163 .map(|_r| ())
1164 }
1165}