Skip to main content

linux_api/
prctl.rs

1use linux_syscall::Result64;
2use linux_syscall::syscall;
3
4use crate::errno::Errno;
5use crate::{bindings, const_conversions};
6
7/// Options for `man 2 prctl`.
8// We want to allow unknown values since newer kernel versions may add new options, and we may want
9// to gracefully handle these options (for example to pass them on to the kernel). Linux also uses
10// the same namespace ("PR_") for both options and argument flags (for example the `option`
11// `PR_SET_FP_MODE` and the bitflag arguments `PR_FP_MODE_FR` and `PR_FP_MODE_FRE` in `arg2`). We
12// don't want bitflags in this struct, so when adding new "PR_" entries, make sure they correspond
13// with prctl "options" and not "arguments".
14#[derive(PartialEq, Eq)]
15pub struct PrctlOp(i32);
16
17impl PrctlOp {
18    pub const PR_SET_PDEATHSIG: Self = Self::from_u32(bindings::LINUX_PR_SET_PDEATHSIG);
19    pub const PR_GET_PDEATHSIG: Self = Self::from_u32(bindings::LINUX_PR_GET_PDEATHSIG);
20    pub const PR_GET_DUMPABLE: Self = Self::from_u32(bindings::LINUX_PR_GET_DUMPABLE);
21    pub const PR_SET_DUMPABLE: Self = Self::from_u32(bindings::LINUX_PR_SET_DUMPABLE);
22    pub const PR_GET_UNALIGN: Self = Self::from_u32(bindings::LINUX_PR_GET_UNALIGN);
23    pub const PR_SET_UNALIGN: Self = Self::from_u32(bindings::LINUX_PR_SET_UNALIGN);
24    pub const PR_GET_KEEPCAPS: Self = Self::from_u32(bindings::LINUX_PR_GET_KEEPCAPS);
25    pub const PR_SET_KEEPCAPS: Self = Self::from_u32(bindings::LINUX_PR_SET_KEEPCAPS);
26    pub const PR_GET_FPEMU: Self = Self::from_u32(bindings::LINUX_PR_GET_FPEMU);
27    pub const PR_SET_FPEMU: Self = Self::from_u32(bindings::LINUX_PR_SET_FPEMU);
28    pub const PR_GET_FPEXC: Self = Self::from_u32(bindings::LINUX_PR_GET_FPEXC);
29    pub const PR_SET_FPEXC: Self = Self::from_u32(bindings::LINUX_PR_SET_FPEXC);
30    pub const PR_GET_TIMING: Self = Self::from_u32(bindings::LINUX_PR_GET_TIMING);
31    pub const PR_SET_TIMING: Self = Self::from_u32(bindings::LINUX_PR_SET_TIMING);
32    pub const PR_SET_NAME: Self = Self::from_u32(bindings::LINUX_PR_SET_NAME);
33    pub const PR_GET_NAME: Self = Self::from_u32(bindings::LINUX_PR_GET_NAME);
34    pub const PR_GET_ENDIAN: Self = Self::from_u32(bindings::LINUX_PR_GET_ENDIAN);
35    pub const PR_SET_ENDIAN: Self = Self::from_u32(bindings::LINUX_PR_SET_ENDIAN);
36    pub const PR_GET_SECCOMP: Self = Self::from_u32(bindings::LINUX_PR_GET_SECCOMP);
37    pub const PR_SET_SECCOMP: Self = Self::from_u32(bindings::LINUX_PR_SET_SECCOMP);
38    pub const PR_CAPBSET_READ: Self = Self::from_u32(bindings::LINUX_PR_CAPBSET_READ);
39    pub const PR_CAPBSET_DROP: Self = Self::from_u32(bindings::LINUX_PR_CAPBSET_DROP);
40    pub const PR_GET_TSC: Self = Self::from_u32(bindings::LINUX_PR_GET_TSC);
41    pub const PR_SET_TSC: Self = Self::from_u32(bindings::LINUX_PR_SET_TSC);
42    pub const PR_GET_SECUREBITS: Self = Self::from_u32(bindings::LINUX_PR_GET_SECUREBITS);
43    pub const PR_SET_SECUREBITS: Self = Self::from_u32(bindings::LINUX_PR_SET_SECUREBITS);
44    pub const PR_SET_TIMERSLACK: Self = Self::from_u32(bindings::LINUX_PR_SET_TIMERSLACK);
45    pub const PR_GET_TIMERSLACK: Self = Self::from_u32(bindings::LINUX_PR_GET_TIMERSLACK);
46    pub const PR_TASK_PERF_EVENTS_DISABLE: Self =
47        Self::from_u32(bindings::LINUX_PR_TASK_PERF_EVENTS_DISABLE);
48    pub const PR_TASK_PERF_EVENTS_ENABLE: Self =
49        Self::from_u32(bindings::LINUX_PR_TASK_PERF_EVENTS_ENABLE);
50    pub const PR_MCE_KILL: Self = Self::from_u32(bindings::LINUX_PR_MCE_KILL);
51    pub const PR_SET_MM: Self = Self::from_u32(bindings::LINUX_PR_SET_MM);
52    pub const PR_MCE_KILL_GET: Self = Self::from_u32(bindings::LINUX_PR_MCE_KILL_GET);
53    pub const PR_SET_PTRACER: Self = Self::from_u32(bindings::LINUX_PR_SET_PTRACER);
54    pub const PR_SET_CHILD_SUBREAPER: Self = Self::from_u32(bindings::LINUX_PR_SET_CHILD_SUBREAPER);
55    pub const PR_GET_CHILD_SUBREAPER: Self = Self::from_u32(bindings::LINUX_PR_GET_CHILD_SUBREAPER);
56    pub const PR_SET_NO_NEW_PRIVS: Self = Self::from_u32(bindings::LINUX_PR_SET_NO_NEW_PRIVS);
57    pub const PR_GET_NO_NEW_PRIVS: Self = Self::from_u32(bindings::LINUX_PR_GET_NO_NEW_PRIVS);
58    pub const PR_GET_TID_ADDRESS: Self = Self::from_u32(bindings::LINUX_PR_GET_TID_ADDRESS);
59    pub const PR_SET_THP_DISABLE: Self = Self::from_u32(bindings::LINUX_PR_SET_THP_DISABLE);
60    pub const PR_GET_THP_DISABLE: Self = Self::from_u32(bindings::LINUX_PR_GET_THP_DISABLE);
61    pub const PR_MPX_ENABLE_MANAGEMENT: Self =
62        Self::from_u32(bindings::LINUX_PR_MPX_ENABLE_MANAGEMENT);
63    pub const PR_MPX_DISABLE_MANAGEMENT: Self =
64        Self::from_u32(bindings::LINUX_PR_MPX_DISABLE_MANAGEMENT);
65    pub const PR_SET_FP_MODE: Self = Self::from_u32(bindings::LINUX_PR_SET_FP_MODE);
66    pub const PR_GET_FP_MODE: Self = Self::from_u32(bindings::LINUX_PR_GET_FP_MODE);
67    pub const PR_CAP_AMBIENT: Self = Self::from_u32(bindings::LINUX_PR_CAP_AMBIENT);
68    pub const PR_SVE_SET_VL: Self = Self::from_u32(bindings::LINUX_PR_SVE_SET_VL);
69    pub const PR_SVE_GET_VL: Self = Self::from_u32(bindings::LINUX_PR_SVE_GET_VL);
70    pub const PR_GET_SPECULATION_CTRL: Self =
71        Self::from_u32(bindings::LINUX_PR_GET_SPECULATION_CTRL);
72    pub const PR_SET_SPECULATION_CTRL: Self =
73        Self::from_u32(bindings::LINUX_PR_SET_SPECULATION_CTRL);
74    pub const PR_PAC_RESET_KEYS: Self = Self::from_u32(bindings::LINUX_PR_PAC_RESET_KEYS);
75    pub const PR_SET_TAGGED_ADDR_CTRL: Self =
76        Self::from_u32(bindings::LINUX_PR_SET_TAGGED_ADDR_CTRL);
77    pub const PR_GET_TAGGED_ADDR_CTRL: Self =
78        Self::from_u32(bindings::LINUX_PR_GET_TAGGED_ADDR_CTRL);
79    pub const PR_SET_IO_FLUSHER: Self = Self::from_u32(bindings::LINUX_PR_SET_IO_FLUSHER);
80    pub const PR_GET_IO_FLUSHER: Self = Self::from_u32(bindings::LINUX_PR_GET_IO_FLUSHER);
81    pub const PR_SET_SYSCALL_USER_DISPATCH: Self =
82        Self::from_u32(bindings::LINUX_PR_SET_SYSCALL_USER_DISPATCH);
83    pub const PR_PAC_SET_ENABLED_KEYS: Self =
84        Self::from_u32(bindings::LINUX_PR_PAC_SET_ENABLED_KEYS);
85    pub const PR_PAC_GET_ENABLED_KEYS: Self =
86        Self::from_u32(bindings::LINUX_PR_PAC_GET_ENABLED_KEYS);
87    pub const PR_SCHED_CORE: Self = Self::from_u32(bindings::LINUX_PR_SCHED_CORE);
88    pub const PR_SME_SET_VL: Self = Self::from_u32(bindings::LINUX_PR_SME_SET_VL);
89    pub const PR_SME_GET_VL: Self = Self::from_u32(bindings::LINUX_PR_SME_GET_VL);
90    pub const PR_SET_MDWE: Self = Self::from_u32(bindings::LINUX_PR_SET_MDWE);
91    pub const PR_GET_MDWE: Self = Self::from_u32(bindings::LINUX_PR_GET_MDWE);
92    pub const PR_SET_VMA: Self = Self::from_u32(bindings::LINUX_PR_SET_VMA);
93    pub const PR_GET_AUXV: Self = Self::from_u32(bindings::LINUX_PR_GET_AUXV);
94    pub const PR_SET_MEMORY_MERGE: Self = Self::from_u32(bindings::LINUX_PR_SET_MEMORY_MERGE);
95    pub const PR_GET_MEMORY_MERGE: Self = Self::from_u32(bindings::LINUX_PR_GET_MEMORY_MERGE);
96    pub const PR_RISCV_V_SET_CONTROL: Self = Self::from_u32(bindings::LINUX_PR_RISCV_V_SET_CONTROL);
97    pub const PR_RISCV_V_GET_CONTROL: Self = Self::from_u32(bindings::LINUX_PR_RISCV_V_GET_CONTROL);
98    pub const PR_RISCV_SET_ICACHE_FLUSH_CTX: Self =
99        Self::from_u32(bindings::LINUX_PR_RISCV_SET_ICACHE_FLUSH_CTX);
100    pub const PR_PPC_GET_DEXCR: Self = Self::from_u32(bindings::LINUX_PR_PPC_GET_DEXCR);
101    pub const PR_PPC_SET_DEXCR: Self = Self::from_u32(bindings::LINUX_PR_PPC_SET_DEXCR);
102    pub const PR_GET_SHADOW_STACK_STATUS: Self =
103        Self::from_u32(bindings::LINUX_PR_GET_SHADOW_STACK_STATUS);
104    pub const PR_SET_SHADOW_STACK_STATUS: Self =
105        Self::from_u32(bindings::LINUX_PR_SET_SHADOW_STACK_STATUS);
106    pub const PR_LOCK_SHADOW_STACK_STATUS: Self =
107        Self::from_u32(bindings::LINUX_PR_LOCK_SHADOW_STACK_STATUS);
108    pub const PR_TIMER_CREATE_RESTORE_IDS: Self =
109        Self::from_u32(bindings::LINUX_PR_TIMER_CREATE_RESTORE_IDS);
110    pub const PR_FUTEX_HASH: Self = Self::from_u32(bindings::LINUX_PR_FUTEX_HASH);
111    pub const PR_GET_CFI: Self = Self::from_u32(bindings::LINUX_PR_GET_CFI);
112    pub const PR_SET_CFI: Self = Self::from_u32(bindings::LINUX_PR_SET_CFI);
113    pub const PR_RSEQ_SLICE_EXTENSION: Self =
114        Self::from_u32(bindings::LINUX_PR_RSEQ_SLICE_EXTENSION);
115
116    // NOTE: only add prctl options here (not prctl args), and add new entries to `to_str` below
117
118    pub const fn new(val: i32) -> Self {
119        Self(val)
120    }
121
122    pub const fn val(&self) -> i32 {
123        self.0
124    }
125
126    const fn from_u32(val: u32) -> Self {
127        Self::new(const_conversions::i32_from_u32(val))
128    }
129
130    pub const fn to_str(&self) -> Option<&'static str> {
131        match *self {
132            Self::PR_SET_PDEATHSIG => Some("PR_SET_PDEATHSIG"),
133            Self::PR_GET_PDEATHSIG => Some("PR_GET_PDEATHSIG"),
134            Self::PR_GET_DUMPABLE => Some("PR_GET_DUMPABLE"),
135            Self::PR_SET_DUMPABLE => Some("PR_SET_DUMPABLE"),
136            Self::PR_GET_UNALIGN => Some("PR_GET_UNALIGN"),
137            Self::PR_SET_UNALIGN => Some("PR_SET_UNALIGN"),
138            Self::PR_GET_KEEPCAPS => Some("PR_GET_KEEPCAPS"),
139            Self::PR_SET_KEEPCAPS => Some("PR_SET_KEEPCAPS"),
140            Self::PR_GET_FPEMU => Some("PR_GET_FPEMU"),
141            Self::PR_SET_FPEMU => Some("PR_SET_FPEMU"),
142            Self::PR_GET_FPEXC => Some("PR_GET_FPEXC"),
143            Self::PR_SET_FPEXC => Some("PR_SET_FPEXC"),
144            Self::PR_GET_TIMING => Some("PR_GET_TIMING"),
145            Self::PR_SET_TIMING => Some("PR_SET_TIMING"),
146            Self::PR_SET_NAME => Some("PR_SET_NAME"),
147            Self::PR_GET_NAME => Some("PR_GET_NAME"),
148            Self::PR_GET_ENDIAN => Some("PR_GET_ENDIAN"),
149            Self::PR_SET_ENDIAN => Some("PR_SET_ENDIAN"),
150            Self::PR_GET_SECCOMP => Some("PR_GET_SECCOMP"),
151            Self::PR_SET_SECCOMP => Some("PR_SET_SECCOMP"),
152            Self::PR_CAPBSET_READ => Some("PR_CAPBSET_READ"),
153            Self::PR_CAPBSET_DROP => Some("PR_CAPBSET_DROP"),
154            Self::PR_GET_TSC => Some("PR_GET_TSC"),
155            Self::PR_SET_TSC => Some("PR_SET_TSC"),
156            Self::PR_GET_SECUREBITS => Some("PR_GET_SECUREBITS"),
157            Self::PR_SET_SECUREBITS => Some("PR_SET_SECUREBITS"),
158            Self::PR_SET_TIMERSLACK => Some("PR_SET_TIMERSLACK"),
159            Self::PR_GET_TIMERSLACK => Some("PR_GET_TIMERSLACK"),
160            Self::PR_TASK_PERF_EVENTS_DISABLE => Some("PR_TASK_PERF_EVENTS_DISABLE"),
161            Self::PR_TASK_PERF_EVENTS_ENABLE => Some("PR_TASK_PERF_EVENTS_ENABLE"),
162            Self::PR_MCE_KILL => Some("PR_MCE_KILL"),
163            Self::PR_SET_MM => Some("PR_SET_MM"),
164            Self::PR_SET_PTRACER => Some("PR_SET_PTRACER"),
165            Self::PR_SET_CHILD_SUBREAPER => Some("PR_SET_CHILD_SUBREAPER"),
166            Self::PR_GET_CHILD_SUBREAPER => Some("PR_GET_CHILD_SUBREAPER"),
167            Self::PR_SET_NO_NEW_PRIVS => Some("PR_SET_NO_NEW_PRIVS"),
168            Self::PR_GET_NO_NEW_PRIVS => Some("PR_GET_NO_NEW_PRIVS"),
169            Self::PR_GET_TID_ADDRESS => Some("PR_GET_TID_ADDRESS"),
170            Self::PR_SET_THP_DISABLE => Some("PR_SET_THP_DISABLE"),
171            Self::PR_GET_THP_DISABLE => Some("PR_GET_THP_DISABLE"),
172            Self::PR_MPX_ENABLE_MANAGEMENT => Some("PR_MPX_ENABLE_MANAGEMENT"),
173            Self::PR_MPX_DISABLE_MANAGEMENT => Some("PR_MPX_DISABLE_MANAGEMENT"),
174            Self::PR_SET_FP_MODE => Some("PR_SET_FP_MODE"),
175            Self::PR_GET_FP_MODE => Some("PR_GET_FP_MODE"),
176            Self::PR_CAP_AMBIENT => Some("PR_CAP_AMBIENT"),
177            Self::PR_SVE_SET_VL => Some("PR_SVE_SET_VL"),
178            Self::PR_SVE_GET_VL => Some("PR_SVE_GET_VL"),
179            Self::PR_GET_SPECULATION_CTRL => Some("PR_GET_SPECULATION_CTRL"),
180            Self::PR_SET_SPECULATION_CTRL => Some("PR_SET_SPECULATION_CTRL"),
181            Self::PR_PAC_RESET_KEYS => Some("PR_PAC_RESET_KEYS"),
182            Self::PR_SET_TAGGED_ADDR_CTRL => Some("PR_SET_TAGGED_ADDR_CTRL"),
183            Self::PR_GET_TAGGED_ADDR_CTRL => Some("PR_GET_TAGGED_ADDR_CTRL"),
184            Self::PR_SET_IO_FLUSHER => Some("PR_SET_IO_FLUSHER"),
185            Self::PR_GET_IO_FLUSHER => Some("PR_GET_IO_FLUSHER"),
186            Self::PR_SET_SYSCALL_USER_DISPATCH => Some("PR_SET_SYSCALL_USER_DISPATCH"),
187            Self::PR_PAC_SET_ENABLED_KEYS => Some("PR_PAC_SET_ENABLED_KEYS"),
188            Self::PR_PAC_GET_ENABLED_KEYS => Some("PR_PAC_GET_ENABLED_KEYS"),
189            Self::PR_SCHED_CORE => Some("PR_SCHED_CORE"),
190            Self::PR_SME_SET_VL => Some("PR_SME_SET_VL"),
191            Self::PR_SME_GET_VL => Some("PR_SME_GET_VL"),
192            Self::PR_SET_MDWE => Some("PR_SET_MDWE"),
193            Self::PR_GET_MDWE => Some("PR_GET_MDWE"),
194            Self::PR_SET_VMA => Some("PR_SET_VMA"),
195            Self::PR_GET_AUXV => Some("PR_GET_AUXV"),
196            Self::PR_SET_MEMORY_MERGE => Some("PR_SET_MEMORY_MERGE"),
197            Self::PR_GET_MEMORY_MERGE => Some("PR_GET_MEMORY_MERGE"),
198            Self::PR_RISCV_V_SET_CONTROL => Some("PR_RISCV_V_SET_CONTROL"),
199            Self::PR_RISCV_V_GET_CONTROL => Some("PR_RISCV_V_GET_CONTROL"),
200            Self::PR_RISCV_SET_ICACHE_FLUSH_CTX => Some("PR_RISCV_SET_ICACHE_FLUSH_CTX"),
201            Self::PR_PPC_GET_DEXCR => Some("PR_PPC_GET_DEXCR"),
202            Self::PR_PPC_SET_DEXCR => Some("PR_PPC_SET_DEXCR"),
203            Self::PR_GET_SHADOW_STACK_STATUS => Some("PR_GET_SHADOW_STACK_STATUS"),
204            Self::PR_SET_SHADOW_STACK_STATUS => Some("PR_SET_SHADOW_STACK_STATUS"),
205            Self::PR_LOCK_SHADOW_STACK_STATUS => Some("PR_LOCK_SHADOW_STACK_STATUS"),
206            Self::PR_TIMER_CREATE_RESTORE_IDS => Some("PR_TIMER_CREATE_RESTORE_IDS"),
207            Self::PR_FUTEX_HASH => Some("PR_FUTEX_HASH"),
208            Self::PR_GET_CFI => Some("PR_GET_CFI"),
209            Self::PR_SET_CFI => Some("PR_SET_CFI"),
210            Self::PR_RSEQ_SLICE_EXTENSION => Some("PR_RSEQ_SLICE_EXTENSION"),
211            _ => None,
212        }
213    }
214}
215
216impl core::fmt::Display for PrctlOp {
217    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
218        match self.to_str() {
219            Some(s) => formatter.write_str(s),
220            None => write!(formatter, "(unknown prctl option {})", self.0),
221        }
222    }
223}
224
225impl core::fmt::Debug for PrctlOp {
226    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
227        match self.to_str() {
228            Some(s) => write!(formatter, "PrctlOp::{s}"),
229            None => write!(formatter, "PrctlOp::<{}>", self.0),
230        }
231    }
232}
233
234impl From<PrctlOp> for i32 {
235    #[inline]
236    fn from(val: PrctlOp) -> Self {
237        val.0
238    }
239}
240
241impl From<i32> for PrctlOp {
242    #[inline]
243    fn from(val: i32) -> Self {
244        Self::new(val)
245    }
246}
247
248#[derive(PartialEq, Eq)]
249pub struct ArchPrctlOp(i32);
250
251impl ArchPrctlOp {
252    pub const ARCH_SET_CPUID: Self = Self::from_u32(bindings::LINUX_ARCH_SET_CPUID);
253    pub const ARCH_GET_CPUID: Self = Self::from_u32(bindings::LINUX_ARCH_GET_CPUID);
254    pub const ARCH_SET_FS: Self = Self::from_u32(bindings::LINUX_ARCH_SET_FS);
255    pub const ARCH_GET_FS: Self = Self::from_u32(bindings::LINUX_ARCH_GET_FS);
256    pub const ARCH_SET_GS: Self = Self::from_u32(bindings::LINUX_ARCH_SET_GS);
257    pub const ARCH_GET_GS: Self = Self::from_u32(bindings::LINUX_ARCH_GET_GS);
258    pub const ARCH_GET_XCOMP_SUPP: Self = Self::from_u32(bindings::LINUX_ARCH_GET_XCOMP_SUPP);
259    pub const ARCH_GET_XCOMP_PERM: Self = Self::from_u32(bindings::LINUX_ARCH_GET_XCOMP_PERM);
260    pub const ARCH_REQ_XCOMP_PERM: Self = Self::from_u32(bindings::LINUX_ARCH_REQ_XCOMP_PERM);
261    pub const ARCH_GET_XCOMP_GUEST_PERM: Self =
262        Self::from_u32(bindings::LINUX_ARCH_GET_XCOMP_GUEST_PERM);
263    pub const ARCH_REQ_XCOMP_GUEST_PERM: Self =
264        Self::from_u32(bindings::LINUX_ARCH_REQ_XCOMP_GUEST_PERM);
265    pub const ARCH_XCOMP_TILECFG: Self = Self::from_u32(bindings::LINUX_ARCH_XCOMP_TILECFG);
266    pub const ARCH_XCOMP_TILEDATA: Self = Self::from_u32(bindings::LINUX_ARCH_XCOMP_TILEDATA);
267    pub const ARCH_MAP_VDSO_X32: Self = Self::from_u32(bindings::LINUX_ARCH_MAP_VDSO_X32);
268    pub const ARCH_MAP_VDSO_32: Self = Self::from_u32(bindings::LINUX_ARCH_MAP_VDSO_32);
269    pub const ARCH_MAP_VDSO_64: Self = Self::from_u32(bindings::LINUX_ARCH_MAP_VDSO_64);
270    pub const ARCH_GET_UNTAG_MASK: Self = Self::from_u32(bindings::LINUX_ARCH_GET_UNTAG_MASK);
271    pub const ARCH_ENABLE_TAGGED_ADDR: Self =
272        Self::from_u32(bindings::LINUX_ARCH_ENABLE_TAGGED_ADDR);
273    pub const ARCH_GET_MAX_TAG_BITS: Self = Self::from_u32(bindings::LINUX_ARCH_GET_MAX_TAG_BITS);
274    pub const ARCH_FORCE_TAGGED_SVA: Self = Self::from_u32(bindings::LINUX_ARCH_FORCE_TAGGED_SVA);
275    pub const ARCH_SHSTK_ENABLE: Self = Self::from_u32(bindings::LINUX_ARCH_SHSTK_ENABLE);
276    pub const ARCH_SHSTK_DISABLE: Self = Self::from_u32(bindings::LINUX_ARCH_SHSTK_DISABLE);
277    pub const ARCH_SHSTK_LOCK: Self = Self::from_u32(bindings::LINUX_ARCH_SHSTK_LOCK);
278    pub const ARCH_SHSTK_UNLOCK: Self = Self::from_u32(bindings::LINUX_ARCH_SHSTK_UNLOCK);
279    pub const ARCH_SHSTK_STATUS: Self = Self::from_u32(bindings::LINUX_ARCH_SHSTK_STATUS);
280    pub const ARCH_SHSTK_SHSTK: Self = Self::from_u32(bindings::LINUX_ARCH_SHSTK_SHSTK);
281    pub const ARCH_SHSTK_WRSS: Self = Self::from_u32(bindings::LINUX_ARCH_SHSTK_WRSS);
282
283    pub const fn new(val: i32) -> Self {
284        Self(val)
285    }
286
287    const fn from_u32(val: u32) -> Self {
288        Self::new(const_conversions::i32_from_u32(val))
289    }
290
291    pub const fn to_str(&self) -> Option<&'static str> {
292        match *self {
293            Self::ARCH_SET_CPUID => Some("ARCH_SET_CPUID"),
294            Self::ARCH_GET_CPUID => Some("ARCH_GET_CPUID"),
295            Self::ARCH_GET_FS => Some("ARCH_GET_FS"),
296            Self::ARCH_SET_FS => Some("ARCH_SET_FS"),
297            Self::ARCH_GET_GS => Some("ARCH_GET_GS"),
298            Self::ARCH_SET_GS => Some("ARCH_SET_GS"),
299            Self::ARCH_GET_XCOMP_SUPP => Some("ARCH_GET_XCOMP_SUPP"),
300            Self::ARCH_GET_XCOMP_PERM => Some("ARCH_GET_XCOMP_PERM"),
301            Self::ARCH_REQ_XCOMP_PERM => Some("ARCH_REQ_XCOMP_PERM"),
302            Self::ARCH_GET_XCOMP_GUEST_PERM => Some("ARCH_GET_XCOMP_GUEST_PERM"),
303            Self::ARCH_REQ_XCOMP_GUEST_PERM => Some("ARCH_REQ_XCOMP_GUEST_PERM"),
304            Self::ARCH_XCOMP_TILECFG => Some("ARCH_XCOMP_TILECFG"),
305            Self::ARCH_XCOMP_TILEDATA => Some("ARCH_XCOMP_TILEDATA"),
306            Self::ARCH_MAP_VDSO_X32 => Some("ARCH_MAP_VDSO_X32"),
307            Self::ARCH_MAP_VDSO_32 => Some("ARCH_MAP_VDSO_32"),
308            Self::ARCH_MAP_VDSO_64 => Some("ARCH_MAP_VDSO_64"),
309            Self::ARCH_GET_UNTAG_MASK => Some("ARCH_GET_UNTAG_MASK"),
310            Self::ARCH_ENABLE_TAGGED_ADDR => Some("ARCH_ENABLE_TAGGED_ADDR"),
311            Self::ARCH_GET_MAX_TAG_BITS => Some("ARCH_GET_MAX_TAG_BITS"),
312            Self::ARCH_FORCE_TAGGED_SVA => Some("ARCH_FORCE_TAGGED_SVA"),
313            Self::ARCH_SHSTK_ENABLE => Some("ARCH_SHSTK_ENABLE"),
314            Self::ARCH_SHSTK_DISABLE => Some("ARCH_SHSTK_DISABLE"),
315            Self::ARCH_SHSTK_LOCK => Some("ARCH_SHSTK_LOCK"),
316            Self::ARCH_SHSTK_UNLOCK => Some("ARCH_SHSTK_UNLOCK"),
317            Self::ARCH_SHSTK_STATUS => Some("ARCH_SHSTK_STATUS"),
318            Self::ARCH_SHSTK_SHSTK => Some("ARCH_SHSTK_SHSTK"),
319            Self::ARCH_SHSTK_WRSS => Some("ARCH_SHSTK_WRSS"),
320            _ => None,
321        }
322    }
323}
324
325impl From<ArchPrctlOp> for core::ffi::c_int {
326    fn from(value: ArchPrctlOp) -> Self {
327        value.0
328    }
329}
330
331impl core::fmt::Display for ArchPrctlOp {
332    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
333        match self.to_str() {
334            Some(s) => formatter.write_str(s),
335            None => write!(formatter, "(unknown arch_prctl option {})", self.0),
336        }
337    }
338}
339
340impl core::fmt::Debug for ArchPrctlOp {
341    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
342        match self.to_str() {
343            Some(s) => write!(formatter, "ArchPrctlOp::{s}"),
344            None => write!(formatter, "ArchPrctlOp::<{}>", self.0),
345        }
346    }
347}
348
349/// Execute the `arch_prctl` syscall.
350///
351/// # Safety
352///
353/// Some operations may change OS behavior in a way that violates assumptions
354/// that other code relies on.
355pub unsafe fn arch_prctl_raw(
356    option: core::ffi::c_int,
357    arg2: core::ffi::c_ulong,
358) -> Result<i64, Errno> {
359    unsafe { syscall!(linux_syscall::SYS_arch_prctl, option, arg2) }
360        .try_i64()
361        .map_err(Errno::from)
362}
363
364/// Execute the `arch_prctl` syscall.
365///
366/// # Safety
367///
368/// Some operations may change OS behavior in a way that violates assumptions
369/// that other code relies on.
370pub unsafe fn arch_prctl(option: ArchPrctlOp, arg2: u64) -> Result<i64, Errno> {
371    unsafe { arch_prctl_raw(option.into(), arg2) }
372}