1 //! Linux `prctl` wrappers.
2 //!
3 //! Rustix wraps variadic/dynamic-dispatch functions like `prctl` in
4 //! type-safe wrappers.
5 //!
6 //! # Safety
7 //!
8 //! The inner `prctl` calls are dynamically typed and must be called
9 //! correctly.
10 #![allow(unsafe_code)]
11
12 use core::mem::MaybeUninit;
13 use core::num::NonZeroU64;
14 use core::ptr;
15 use core::ptr::NonNull;
16 use core::sync::atomic::AtomicU8;
17
18 use bitflags::bitflags;
19
20 use crate::backend::c::{c_int, c_uint, c_void};
21 use crate::backend::prctl::syscalls;
22 use crate::ffi::CStr;
23 #[cfg(feature = "alloc")]
24 use crate::ffi::CString;
25 use crate::io;
26 use crate::pid::Pid;
27 use crate::prctl::{
28 prctl_1arg, prctl_2args, prctl_3args, prctl_get_at_arg2_optional, PointerAuthenticationKeys,
29 };
30 use crate::utils::as_ptr;
31
32 //
33 // PR_GET_KEEPCAPS/PR_SET_KEEPCAPS
34 //
35
36 const PR_GET_KEEPCAPS: c_int = 7;
37
38 /// Get the current state of the calling thread's `keep capabilities` flag.
39 ///
40 /// # References
41 /// - [`prctl(PR_GET_KEEPCAPS,...)`]
42 ///
43 /// [`prctl(PR_GET_KEEPCAPS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
44 #[inline]
get_keep_capabilities() -> io::Result<bool>45 pub fn get_keep_capabilities() -> io::Result<bool> {
46 unsafe { prctl_1arg(PR_GET_KEEPCAPS) }.map(|r| r != 0)
47 }
48
49 const PR_SET_KEEPCAPS: c_int = 8;
50
51 /// Set the state of the calling thread's `keep capabilities` flag.
52 ///
53 /// # References
54 /// - [`prctl(PR_SET_KEEPCAPS,...)`]
55 ///
56 /// [`prctl(PR_SET_KEEPCAPS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
57 #[inline]
set_keep_capabilities(enable: bool) -> io::Result<()>58 pub fn set_keep_capabilities(enable: bool) -> io::Result<()> {
59 unsafe { prctl_2args(PR_SET_KEEPCAPS, usize::from(enable) as *mut _) }.map(|_r| ())
60 }
61
62 //
63 // PR_GET_NAME/PR_SET_NAME
64 //
65
66 #[cfg(feature = "alloc")]
67 const PR_GET_NAME: c_int = 16;
68
69 /// Get the name of the calling thread.
70 ///
71 /// # References
72 /// - [`prctl(PR_GET_NAME,...)`]
73 ///
74 /// [`prctl(PR_GET_NAME,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
75 #[inline]
76 #[cfg(feature = "alloc")]
name() -> io::Result<CString>77 pub fn name() -> io::Result<CString> {
78 let mut buffer = [0_u8; 16];
79 unsafe { prctl_2args(PR_GET_NAME, buffer.as_mut_ptr().cast())? };
80
81 let len = buffer.iter().position(|&x| x == 0_u8).unwrap_or(0);
82 CString::new(&buffer[..len]).map_err(|_r| io::Errno::ILSEQ)
83 }
84
85 const PR_SET_NAME: c_int = 15;
86
87 /// Set the name of the calling thread.
88 ///
89 /// Unlike `pthread_setname_np`, this function silently truncates the name to
90 /// 16 bytes, as the Linux syscall does.
91 ///
92 /// # References
93 /// - [`prctl(PR_SET_NAME,...)`]
94 ///
95 /// [`prctl(PR_SET_NAME,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
96 #[inline]
set_name(name: &CStr) -> io::Result<()>97 pub fn set_name(name: &CStr) -> io::Result<()> {
98 unsafe { prctl_2args(PR_SET_NAME, name.as_ptr() as *mut _) }.map(|_r| ())
99 }
100
101 //
102 // PR_GET_SECCOMP/PR_SET_SECCOMP
103 //
104
105 //const PR_GET_SECCOMP: c_int = 21;
106
107 const SECCOMP_MODE_DISABLED: i32 = 0;
108 const SECCOMP_MODE_STRICT: i32 = 1;
109 const SECCOMP_MODE_FILTER: i32 = 2;
110
111 /// `SECCOMP_MODE_*`.
112 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
113 #[repr(i32)]
114 pub enum SecureComputingMode {
115 /// Secure computing is not in use.
116 Disabled = SECCOMP_MODE_DISABLED,
117 /// Use hard-coded filter.
118 Strict = SECCOMP_MODE_STRICT,
119 /// Use user-supplied filter.
120 Filter = SECCOMP_MODE_FILTER,
121 }
122
123 impl TryFrom<i32> for SecureComputingMode {
124 type Error = io::Errno;
125
try_from(value: i32) -> Result<Self, Self::Error>126 fn try_from(value: i32) -> Result<Self, Self::Error> {
127 match value {
128 SECCOMP_MODE_DISABLED => Ok(Self::Disabled),
129 SECCOMP_MODE_STRICT => Ok(Self::Strict),
130 SECCOMP_MODE_FILTER => Ok(Self::Filter),
131 _ => Err(io::Errno::RANGE),
132 }
133 }
134 }
135
136 /*
137 /// Get the secure computing mode of the calling thread.
138 ///
139 /// If the caller is not in secure computing mode, this returns
140 /// [`SecureComputingMode::Disabled`]. If the caller is in strict secure
141 /// computing mode, then this call will cause a [`Signal::Kill`] signal to be
142 /// sent to the process. If the caller is in filter mode, and this system call
143 /// is allowed by the seccomp filters, it returns
144 /// [`SecureComputingMode::Filter`]; otherwise, the process is killed with a
145 /// [`Signal::Kill`] signal.
146 ///
147 /// Since Linux 3.8, the Seccomp field of the `/proc/[pid]/status` file
148 /// provides a method of obtaining the same information, without the risk that
149 /// the process is killed; see [the `proc` manual page].
150 ///
151 /// # References
152 /// - [`prctl(PR_GET_SECCOMP,...)`]
153 ///
154 /// [`prctl(PR_GET_SECCOMP,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
155 /// [the `proc` manual page]: https://man7.org/linux/man-pages/man5/proc.5.html
156 #[inline]
157 pub fn secure_computing_mode() -> io::Result<SecureComputingMode> {
158 unsafe { prctl_1arg(PR_GET_SECCOMP) }.and_then(TryInto::try_into)
159 }
160 */
161
162 const PR_SET_SECCOMP: c_int = 22;
163
164 /// Set the secure computing mode for the calling thread, to limit the
165 /// available system calls.
166 ///
167 /// # References
168 /// - [`prctl(PR_SET_SECCOMP,...)`]
169 ///
170 /// [`prctl(PR_SET_SECCOMP,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
171 #[inline]
set_secure_computing_mode(mode: SecureComputingMode) -> io::Result<()>172 pub fn set_secure_computing_mode(mode: SecureComputingMode) -> io::Result<()> {
173 unsafe { prctl_2args(PR_SET_SECCOMP, mode as usize as *mut _) }.map(|_r| ())
174 }
175
176 //
177 // PR_CAPBSET_READ/PR_CAPBSET_DROP
178 //
179
180 const PR_CAPBSET_READ: c_int = 23;
181
182 /// Linux per-thread capability.
183 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
184 #[repr(u32)]
185 pub enum Capability {
186 /// In a system with the `_POSIX_CHOWN_RESTRICTED` option defined, this
187 /// overrides the restriction of changing file ownership and group
188 /// ownership.
189 ChangeOwnership = linux_raw_sys::general::CAP_CHOWN,
190 /// Override all DAC access, including ACL execute access if `_POSIX_ACL`
191 /// is defined. Excluding DAC access covered by
192 /// [`Capability::LinuxImmutable`].
193 DACOverride = linux_raw_sys::general::CAP_DAC_OVERRIDE,
194 /// Overrides all DAC restrictions regarding read and search on files and
195 /// directories, including ACL restrictions if `_POSIX_ACL` is defined.
196 /// Excluding DAC access covered by [`Capability::LinuxImmutable`].
197 DACReadSearch = linux_raw_sys::general::CAP_DAC_READ_SEARCH,
198 /// Overrides all restrictions about allowed operations on files, where
199 /// file owner ID must be equal to the user ID, except where
200 /// [`Capability::FileSetID`] is applicable. It doesn't override MAC
201 /// and DAC restrictions.
202 FileOwner = linux_raw_sys::general::CAP_FOWNER,
203 /// Overrides the following restrictions that the effective user ID shall
204 /// match the file owner ID when setting the `S_ISUID` and `S_ISGID`
205 /// bits on that file; that the effective group ID (or one of the
206 /// supplementary group IDs) shall match the file owner ID when setting the
207 /// `S_ISGID` bit on that file; that the `S_ISUID` and `S_ISGID` bits are
208 /// cleared on successful return from `chown` (not implemented).
209 FileSetID = linux_raw_sys::general::CAP_FSETID,
210 /// Overrides the restriction that the real or effective user ID of a
211 /// process sending a signal must match the real or effective user ID of
212 /// the process receiving the signal.
213 Kill = linux_raw_sys::general::CAP_KILL,
214 /// Allows `setgid` manipulation. Allows `setgroups`. Allows forged gids on
215 /// socket credentials passing.
216 SetGroupID = linux_raw_sys::general::CAP_SETGID,
217 /// Allows `set*uid` manipulation (including fsuid). Allows forged pids on
218 /// socket credentials passing.
219 SetUserID = linux_raw_sys::general::CAP_SETUID,
220 /// Without VFS support for capabilities:
221 /// - Transfer any capability in your permitted set to any pid.
222 /// - remove any capability in your permitted set from any pid. With VFS
223 /// support for capabilities (neither of above, but)
224 /// - Add any capability from current's capability bounding set to the
225 /// current process' inheritable set.
226 /// - Allow taking bits out of capability bounding set.
227 /// - Allow modification of the securebits for a process.
228 SetPermittedCapabilities = linux_raw_sys::general::CAP_SETPCAP,
229 /// Allow modification of `S_IMMUTABLE` and `S_APPEND` file attributes.
230 LinuxImmutable = linux_raw_sys::general::CAP_LINUX_IMMUTABLE,
231 /// Allows binding to TCP/UDP sockets below 1024. Allows binding to ATM
232 /// VCIs below 32.
233 NetBindService = linux_raw_sys::general::CAP_NET_BIND_SERVICE,
234 /// Allow broadcasting, listen to multicast.
235 NetBroadcast = linux_raw_sys::general::CAP_NET_BROADCAST,
236 /// Allow interface configuration. Allow administration of IP firewall,
237 /// masquerading and accounting. Allow setting debug option on sockets.
238 /// Allow modification of routing tables. Allow setting arbitrary
239 /// process / process group ownership on sockets. Allow binding to any
240 /// address for transparent proxying (also via [`Capability::NetRaw`]).
241 /// Allow setting TOS (type of service). Allow setting promiscuous
242 /// mode. Allow clearing driver statistics. Allow multicasting. Allow
243 /// read/write of device-specific registers. Allow activation of ATM
244 /// control sockets.
245 NetAdmin = linux_raw_sys::general::CAP_NET_ADMIN,
246 /// Allow use of `RAW` sockets. Allow use of `PACKET` sockets. Allow
247 /// binding to any address for transparent proxying (also via
248 /// [`Capability::NetAdmin`]).
249 NetRaw = linux_raw_sys::general::CAP_NET_RAW,
250 /// Allow locking of shared memory segments. Allow mlock and mlockall
251 /// (which doesn't really have anything to do with IPC).
252 IPCLock = linux_raw_sys::general::CAP_IPC_LOCK,
253 /// Override IPC ownership checks.
254 IPCOwner = linux_raw_sys::general::CAP_IPC_OWNER,
255 /// Insert and remove kernel modules - modify kernel without limit.
256 SystemModule = linux_raw_sys::general::CAP_SYS_MODULE,
257 /// Allow ioperm/iopl access. Allow sending USB messages to any device via
258 /// `/dev/bus/usb`.
259 SystemRawIO = linux_raw_sys::general::CAP_SYS_RAWIO,
260 /// Allow use of `chroot`.
261 SystemChangeRoot = linux_raw_sys::general::CAP_SYS_CHROOT,
262 /// Allow `ptrace` of any process.
263 SystemProcessTrace = linux_raw_sys::general::CAP_SYS_PTRACE,
264 /// Allow configuration of process accounting.
265 SystemProcessAccounting = linux_raw_sys::general::CAP_SYS_PACCT,
266 /// Allow configuration of the secure attention key. Allow administration
267 /// of the random device. Allow examination and configuration of disk
268 /// quotas. Allow setting the domainname. Allow setting the hostname.
269 /// Allow `mount` and `umount`, setting up new smb connection.
270 /// Allow some autofs root ioctls. Allow nfsservctl. Allow
271 /// `VM86_REQUEST_IRQ`. Allow to read/write pci config on alpha. Allow
272 /// `irix_prctl` on mips (setstacksize). Allow flushing all cache on
273 /// m68k (`sys_cacheflush`). Allow removing semaphores. Used instead of
274 /// [`Capability::ChangeOwnership`] to "chown" IPC message queues,
275 /// semaphores and shared memory. Allow locking/unlocking of shared
276 /// memory segment. Allow turning swap on/off. Allow forged pids on
277 /// socket credentials passing. Allow setting readahead and
278 /// flushing buffers on block devices. Allow setting geometry in floppy
279 /// driver. Allow turning DMA on/off in `xd` driver. Allow
280 /// administration of md devices (mostly the above, but some
281 /// extra ioctls). Allow tuning the ide driver. Allow access to the nvram
282 /// device. Allow administration of `apm_bios`, serial and bttv (TV)
283 /// device. Allow manufacturer commands in isdn CAPI support driver.
284 /// Allow reading non-standardized portions of pci configuration space.
285 /// Allow DDI debug ioctl on sbpcd driver. Allow setting up serial ports.
286 /// Allow sending raw qic-117 commands. Allow enabling/disabling tagged
287 /// queuing on SCSI controllers and sending arbitrary SCSI commands.
288 /// Allow setting encryption key on loopback filesystem. Allow setting
289 /// zone reclaim policy. Allow everything under
290 /// [`Capability::BerkeleyPacketFilters`] and
291 /// [`Capability::PerformanceMonitoring`] for backward compatibility.
292 SystemAdmin = linux_raw_sys::general::CAP_SYS_ADMIN,
293 /// Allow use of `reboot`.
294 SystemBoot = linux_raw_sys::general::CAP_SYS_BOOT,
295 /// Allow raising priority and setting priority on other (different UID)
296 /// processes. Allow use of FIFO and round-robin (realtime) scheduling
297 /// on own processes and setting the scheduling algorithm used by
298 /// another process. Allow setting cpu affinity on other processes.
299 /// Allow setting realtime ioprio class. Allow setting ioprio class on
300 /// other processes.
301 SystemNice = linux_raw_sys::general::CAP_SYS_NICE,
302 /// Override resource limits. Set resource limits. Override quota limits.
303 /// Override reserved space on ext2 filesystem. Modify data journaling
304 /// mode on ext3 filesystem (uses journaling resources). NOTE: ext2
305 /// honors fsuid when checking for resource overrides, so you can
306 /// override using fsuid too. Override size restrictions on IPC message
307 /// queues. Allow more than 64hz interrupts from the real-time clock.
308 /// Override max number of consoles on console allocation. Override max
309 /// number of keymaps. Control memory reclaim behavior.
310 SystemResource = linux_raw_sys::general::CAP_SYS_RESOURCE,
311 /// Allow manipulation of system clock. Allow `irix_stime` on mips. Allow
312 /// setting the real-time clock.
313 SystemTime = linux_raw_sys::general::CAP_SYS_TIME,
314 /// Allow configuration of tty devices. Allow `vhangup` of tty.
315 SystemTTYConfig = linux_raw_sys::general::CAP_SYS_TTY_CONFIG,
316 /// Allow the privileged aspects of `mknod`.
317 MakeNode = linux_raw_sys::general::CAP_MKNOD,
318 /// Allow taking of leases on files.
319 Lease = linux_raw_sys::general::CAP_LEASE,
320 /// Allow writing the audit log via unicast netlink socket.
321 AuditWrite = linux_raw_sys::general::CAP_AUDIT_WRITE,
322 /// Allow configuration of audit via unicast netlink socket.
323 AuditControl = linux_raw_sys::general::CAP_AUDIT_CONTROL,
324 /// Set or remove capabilities on files. Map `uid=0` into a child user
325 /// namespace.
326 SetFileCapabilities = linux_raw_sys::general::CAP_SETFCAP,
327 /// Override MAC access. The base kernel enforces no MAC policy. An LSM may
328 /// enforce a MAC policy, and if it does and it chooses to implement
329 /// capability based overrides of that policy, this is the capability
330 /// it should use to do so.
331 MACOverride = linux_raw_sys::general::CAP_MAC_OVERRIDE,
332 /// Allow MAC configuration or state changes. The base kernel requires no
333 /// MAC configuration. An LSM may enforce a MAC policy, and if it does
334 /// and it chooses to implement capability based
335 /// checks on modifications to that policy or the data required to maintain
336 /// it, this is the capability it should use to do so.
337 MACAdmin = linux_raw_sys::general::CAP_MAC_ADMIN,
338 /// Allow configuring the kernel's `syslog` (`printk` behaviour).
339 SystemLog = linux_raw_sys::general::CAP_SYSLOG,
340 /// Allow triggering something that will wake the system.
341 WakeAlarm = linux_raw_sys::general::CAP_WAKE_ALARM,
342 /// Allow preventing system suspends.
343 BlockSuspend = linux_raw_sys::general::CAP_BLOCK_SUSPEND,
344 /// Allow reading the audit log via multicast netlink socket.
345 AuditRead = linux_raw_sys::general::CAP_AUDIT_READ,
346 /// Allow system performance and observability privileged operations using
347 /// `perf_events`, `i915_perf` and other kernel subsystems.
348 PerformanceMonitoring = linux_raw_sys::general::CAP_PERFMON,
349 /// This capability allows the following BPF operations:
350 /// - Creating all types of BPF maps
351 /// - Advanced verifier features
352 /// - Indirect variable access
353 /// - Bounded loops
354 /// - BPF to BPF function calls
355 /// - Scalar precision tracking
356 /// - Larger complexity limits
357 /// - Dead code elimination
358 /// - And potentially other features
359 /// - Loading BPF Type Format (BTF) data
360 /// - Retrieve `xlated` and JITed code of BPF programs
361 /// - Use `bpf_spin_lock` helper
362 ///
363 /// [`Capability::PerformanceMonitoring`] relaxes the verifier checks
364 /// further:
365 /// - BPF progs can use of pointer-to-integer conversions
366 /// - speculation attack hardening measures are bypassed
367 /// - `bpf_probe_read` to read arbitrary kernel memory is allowed
368 /// - `bpf_trace_printk` to print kernel memory is allowed
369 ///
370 /// [`Capability::SystemAdmin`] is required to use bpf_probe_write_user.
371 ///
372 /// [`Capability::SystemAdmin`] is required to iterate system-wide loaded
373 /// programs, maps, links, and BTFs, and convert their IDs to file
374 /// descriptors.
375 ///
376 /// [`Capability::PerformanceMonitoring`] and
377 /// [`Capability::BerkeleyPacketFilters`] are required to load tracing
378 /// programs. [`Capability::NetAdmin`] and
379 /// [`Capability::BerkeleyPacketFilters`] are required to load
380 /// networking programs.
381 BerkeleyPacketFilters = linux_raw_sys::general::CAP_BPF,
382 /// Allow checkpoint/restore related operations. Allow PID selection during
383 /// `clone3`. Allow writing to `ns_last_pid`.
384 CheckpointRestore = linux_raw_sys::general::CAP_CHECKPOINT_RESTORE,
385 }
386
387 /// Check if the specified capability is in the calling thread's capability
388 /// bounding set.
389 ///
390 /// # References
391 /// - [`prctl(PR_CAPBSET_READ,...)`]
392 ///
393 /// [`prctl(PR_CAPBSET_READ,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
394 #[inline]
capability_is_in_bounding_set(capability: Capability) -> io::Result<bool>395 pub fn capability_is_in_bounding_set(capability: Capability) -> io::Result<bool> {
396 unsafe { prctl_2args(PR_CAPBSET_READ, capability as usize as *mut _) }.map(|r| r != 0)
397 }
398
399 const PR_CAPBSET_DROP: c_int = 24;
400
401 /// If the calling thread has the [`Capability::SetPermittedCapabilities`]
402 /// capability within its user namespace, then drop the specified capability
403 /// from the thread's capability bounding set.
404 ///
405 /// # References
406 /// - [`prctl(PR_CAPBSET_DROP,...)`]
407 ///
408 /// [`prctl(PR_CAPBSET_DROP,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
409 #[inline]
remove_capability_from_bounding_set(capability: Capability) -> io::Result<()>410 pub fn remove_capability_from_bounding_set(capability: Capability) -> io::Result<()> {
411 unsafe { prctl_2args(PR_CAPBSET_DROP, capability as usize as *mut _) }.map(|_r| ())
412 }
413
414 //
415 // PR_GET_SECUREBITS/PR_SET_SECUREBITS
416 //
417
418 const PR_GET_SECUREBITS: c_int = 27;
419
420 bitflags! {
421 /// `SECBIT_*`.
422 #[repr(transparent)]
423 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
424 pub struct CapabilitiesSecureBits: u32 {
425 /// If this bit is set, then the kernel does not grant capabilities
426 /// when a `set-user-ID-root` program is executed, or when a process
427 /// with an effective or real UID of 0 calls `execve`.
428 const NO_ROOT = 1_u32 << 0;
429 /// Set [`NO_ROOT`] irreversibly.
430 const NO_ROOT_LOCKED = 1_u32 << 1;
431 /// Setting this flag stops the kernel from adjusting the process'
432 /// permitted, effective, and ambient capability sets when the thread's
433 /// effective and filesystem UIDs are switched between zero and nonzero
434 /// values.
435 const NO_SETUID_FIXUP = 1_u32 << 2;
436 /// Set [`NO_SETUID_FIXUP`] irreversibly.
437 const NO_SETUID_FIXUP_LOCKED = 1_u32 << 3;
438 /// Setting this flag allows a thread that has one or more 0 UIDs to
439 /// retain capabilities in its permitted set when it switches all of
440 /// its UIDs to nonzero values.
441 const KEEP_CAPS = 1_u32 << 4;
442 /// Set [`KEEP_CAPS`] irreversibly.
443 const KEEP_CAPS_LOCKED = 1_u32 << 5;
444 /// Setting this flag disallows raising ambient capabilities via the
445 /// `prctl`'s `PR_CAP_AMBIENT_RAISE` operation.
446 const NO_CAP_AMBIENT_RAISE = 1_u32 << 6;
447 /// Set [`NO_CAP_AMBIENT_RAISE`] irreversibly.
448 const NO_CAP_AMBIENT_RAISE_LOCKED = 1_u32 << 7;
449
450 /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
451 const _ = !0;
452 }
453 }
454
455 /// Get the `securebits` flags of the calling thread.
456 ///
457 /// # References
458 /// - [`prctl(PR_GET_SECUREBITS,...)`]
459 ///
460 /// [`prctl(PR_GET_SECUREBITS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
461 #[inline]
capabilities_secure_bits() -> io::Result<CapabilitiesSecureBits>462 pub fn capabilities_secure_bits() -> io::Result<CapabilitiesSecureBits> {
463 let r = unsafe { prctl_1arg(PR_GET_SECUREBITS)? } as c_uint;
464 CapabilitiesSecureBits::from_bits(r).ok_or(io::Errno::RANGE)
465 }
466
467 const PR_SET_SECUREBITS: c_int = 28;
468
469 /// Set the `securebits` flags of the calling thread.
470 ///
471 /// # References
472 /// - [`prctl(PR_SET_SECUREBITS,...)`]
473 ///
474 /// [`prctl(PR_SET_SECUREBITS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
475 #[inline]
set_capabilities_secure_bits(bits: CapabilitiesSecureBits) -> io::Result<()>476 pub fn set_capabilities_secure_bits(bits: CapabilitiesSecureBits) -> io::Result<()> {
477 unsafe { prctl_2args(PR_SET_SECUREBITS, bits.bits() as usize as *mut _) }.map(|_r| ())
478 }
479
480 //
481 // PR_GET_TIMERSLACK/PR_SET_TIMERSLACK
482 //
483
484 const PR_GET_TIMERSLACK: c_int = 30;
485
486 /// Get the `current` timer slack value of the calling thread.
487 ///
488 /// # References
489 /// - [`prctl(PR_GET_TIMERSLACK,...)`]
490 ///
491 /// [`prctl(PR_GET_TIMERSLACK,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
492 #[inline]
current_timer_slack() -> io::Result<u64>493 pub fn current_timer_slack() -> io::Result<u64> {
494 unsafe { prctl_1arg(PR_GET_TIMERSLACK) }.map(|r| r as u64)
495 }
496
497 const PR_SET_TIMERSLACK: c_int = 29;
498
499 /// Sets the `current` timer slack value for the calling thread.
500 ///
501 /// # References
502 /// - [`prctl(PR_SET_TIMERSLACK,...)`]
503 ///
504 /// [`prctl(PR_SET_TIMERSLACK,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
505 #[inline]
set_current_timer_slack(value: Option<NonZeroU64>) -> io::Result<()>506 pub fn set_current_timer_slack(value: Option<NonZeroU64>) -> io::Result<()> {
507 let value = usize::try_from(value.map_or(0, NonZeroU64::get)).map_err(|_r| io::Errno::RANGE)?;
508 unsafe { prctl_2args(PR_SET_TIMERSLACK, value as *mut _) }.map(|_r| ())
509 }
510
511 //
512 // PR_GET_NO_NEW_PRIVS/PR_SET_NO_NEW_PRIVS
513 //
514
515 const PR_GET_NO_NEW_PRIVS: c_int = 39;
516
517 /// Get the value of the `no_new_privs` attribute for the calling thread.
518 ///
519 /// # References
520 /// - [`prctl(PR_GET_NO_NEW_PRIVS,...)`]
521 ///
522 /// [`prctl(PR_GET_NO_NEW_PRIVS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
523 #[inline]
no_new_privs() -> io::Result<bool>524 pub fn no_new_privs() -> io::Result<bool> {
525 unsafe { prctl_1arg(PR_GET_NO_NEW_PRIVS) }.map(|r| r != 0)
526 }
527
528 const PR_SET_NO_NEW_PRIVS: c_int = 38;
529
530 /// Set the calling thread's `no_new_privs` attribute.
531 ///
532 /// # References
533 /// - [`prctl(PR_SET_NO_NEW_PRIVS,...)`]
534 ///
535 /// [`prctl(PR_SET_NO_NEW_PRIVS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
536 #[inline]
set_no_new_privs(no_new_privs: bool) -> io::Result<()>537 pub fn set_no_new_privs(no_new_privs: bool) -> io::Result<()> {
538 unsafe { prctl_2args(PR_SET_NO_NEW_PRIVS, usize::from(no_new_privs) as *mut _) }.map(|_r| ())
539 }
540
541 //
542 // PR_GET_TID_ADDRESS
543 //
544
545 const PR_GET_TID_ADDRESS: c_int = 40;
546
547 /// Get the `clear_child_tid` address set by `set_tid_address`
548 /// and `clone`'s `CLONE_CHILD_CLEARTID` flag.
549 ///
550 /// # References
551 /// - [`prctl(PR_GET_TID_ADDRESS,...)`]
552 ///
553 /// [`prctl(PR_GET_TID_ADDRESS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
554 #[inline]
get_clear_child_tid_address() -> io::Result<Option<NonNull<c_void>>>555 pub fn get_clear_child_tid_address() -> io::Result<Option<NonNull<c_void>>> {
556 unsafe { prctl_get_at_arg2_optional::<*mut c_void>(PR_GET_TID_ADDRESS) }.map(NonNull::new)
557 }
558
559 //
560 // PR_GET_THP_DISABLE/PR_SET_THP_DISABLE
561 //
562
563 const PR_GET_THP_DISABLE: c_int = 42;
564
565 /// Get the current setting of the `THP disable` flag for the calling thread.
566 ///
567 /// # References
568 /// - [`prctl(PR_GET_THP_DISABLE,...)`]
569 ///
570 /// [`prctl(PR_GET_THP_DISABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
571 #[inline]
transparent_huge_pages_are_disabled() -> io::Result<bool>572 pub fn transparent_huge_pages_are_disabled() -> io::Result<bool> {
573 unsafe { prctl_1arg(PR_GET_THP_DISABLE) }.map(|r| r != 0)
574 }
575
576 const PR_SET_THP_DISABLE: c_int = 41;
577
578 /// Set the state of the `THP disable` flag for the calling thread.
579 ///
580 /// # References
581 /// - [`prctl(PR_SET_THP_DISABLE,...)`]
582 ///
583 /// [`prctl(PR_SET_THP_DISABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
584 #[inline]
disable_transparent_huge_pages(thp_disable: bool) -> io::Result<()>585 pub fn disable_transparent_huge_pages(thp_disable: bool) -> io::Result<()> {
586 unsafe { prctl_2args(PR_SET_THP_DISABLE, usize::from(thp_disable) as *mut _) }.map(|_r| ())
587 }
588
589 //
590 // PR_CAP_AMBIENT
591 //
592
593 const PR_CAP_AMBIENT: c_int = 47;
594
595 const PR_CAP_AMBIENT_IS_SET: usize = 1;
596
597 /// Check if the specified capability is in the ambient set.
598 ///
599 /// # References
600 /// - [`prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_IS_SET,...)`]
601 ///
602 /// [`prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_IS_SET,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
603 #[inline]
capability_is_in_ambient_set(capability: Capability) -> io::Result<bool>604 pub fn capability_is_in_ambient_set(capability: Capability) -> io::Result<bool> {
605 let cap = capability as usize as *mut _;
606 unsafe { prctl_3args(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET as *mut _, cap) }.map(|r| r != 0)
607 }
608
609 const PR_CAP_AMBIENT_CLEAR_ALL: usize = 4;
610
611 /// Remove all capabilities from the ambient set.
612 ///
613 /// # References
614 /// - [`prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_CLEAR_ALL,...)`]
615 ///
616 /// [`prctl(PR_CAP_AMBIENT,PR_CAP_AMBIENT_CLEAR_ALL,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
617 #[inline]
clear_ambient_capability_set() -> io::Result<()>618 pub fn clear_ambient_capability_set() -> io::Result<()> {
619 unsafe { prctl_2args(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL as *mut _) }.map(|_r| ())
620 }
621
622 const PR_CAP_AMBIENT_RAISE: usize = 2;
623 const PR_CAP_AMBIENT_LOWER: usize = 3;
624
625 /// Add or remove the specified capability to the ambient set.
626 ///
627 /// # References
628 /// - [`prctl(PR_CAP_AMBIENT,...)`]
629 ///
630 /// [`prctl(PR_CAP_AMBIENT,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
631 #[inline]
configure_capability_in_ambient_set(capability: Capability, enable: bool) -> io::Result<()>632 pub fn configure_capability_in_ambient_set(capability: Capability, enable: bool) -> io::Result<()> {
633 let sub_operation = if enable {
634 PR_CAP_AMBIENT_RAISE
635 } else {
636 PR_CAP_AMBIENT_LOWER
637 };
638 let cap = capability as usize as *mut _;
639
640 unsafe { prctl_3args(PR_CAP_AMBIENT, sub_operation as *mut _, cap) }.map(|_r| ())
641 }
642
643 //
644 // PR_SVE_GET_VL/PR_SVE_SET_VL
645 //
646
647 const PR_SVE_GET_VL: c_int = 51;
648
649 const PR_SVE_VL_LEN_MASK: u32 = 0xffff;
650 const PR_SVE_VL_INHERIT: u32 = 1_u32 << 17;
651
652 /// Scalable Vector Extension vector length configuration.
653 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
654 pub struct SVEVectorLengthConfig {
655 /// Vector length in bytes.
656 pub vector_length_in_bytes: u32,
657 /// Vector length inherited across `execve`.
658 pub vector_length_inherited_across_execve: bool,
659 }
660
661 /// Get the thread's current SVE vector length configuration.
662 ///
663 /// # References
664 /// - [`prctl(PR_SVE_GET_VL,...)`]
665 ///
666 /// [`prctl(PR_SVE_GET_VL,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
667 #[inline]
sve_vector_length_configuration() -> io::Result<SVEVectorLengthConfig>668 pub fn sve_vector_length_configuration() -> io::Result<SVEVectorLengthConfig> {
669 let bits = unsafe { prctl_1arg(PR_SVE_GET_VL)? } as c_uint;
670 Ok(SVEVectorLengthConfig {
671 vector_length_in_bytes: bits & PR_SVE_VL_LEN_MASK,
672 vector_length_inherited_across_execve: (bits & PR_SVE_VL_INHERIT) != 0,
673 })
674 }
675
676 const PR_SVE_SET_VL: c_int = 50;
677
678 const PR_SVE_SET_VL_ONEXEC: u32 = 1_u32 << 18;
679
680 /// Configure the thread's vector length of Scalable Vector Extension.
681 ///
682 /// # References
683 /// - [`prctl(PR_SVE_SET_VL,...)`]
684 ///
685 /// # Safety
686 ///
687 /// Please ensure the conditions necessary to safely call this function,
688 /// as detailed in the references above.
689 ///
690 /// [`prctl(PR_SVE_SET_VL,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
691 #[inline]
set_sve_vector_length_configuration( vector_length_in_bytes: usize, vector_length_inherited_across_execve: bool, defer_change_to_next_execve: bool, ) -> io::Result<()>692 pub unsafe fn set_sve_vector_length_configuration(
693 vector_length_in_bytes: usize,
694 vector_length_inherited_across_execve: bool,
695 defer_change_to_next_execve: bool,
696 ) -> io::Result<()> {
697 let vector_length_in_bytes =
698 u32::try_from(vector_length_in_bytes).map_err(|_r| io::Errno::RANGE)?;
699
700 let mut bits = vector_length_in_bytes & PR_SVE_VL_LEN_MASK;
701
702 if vector_length_inherited_across_execve {
703 bits |= PR_SVE_VL_INHERIT;
704 }
705
706 if defer_change_to_next_execve {
707 bits |= PR_SVE_SET_VL_ONEXEC;
708 }
709
710 prctl_2args(PR_SVE_SET_VL, bits as usize as *mut _).map(|_r| ())
711 }
712
713 //
714 // PR_PAC_RESET_KEYS
715 //
716
717 const PR_PAC_RESET_KEYS: c_int = 54;
718
719 /// Securely reset the thread's pointer authentication keys to fresh random
720 /// values generated by the kernel.
721 ///
722 /// # References
723 /// - [`prctl(PR_PAC_RESET_KEYS,...)`]
724 ///
725 /// # Safety
726 ///
727 /// Please ensure the conditions necessary to safely call this function,
728 /// as detailed in the references above.
729 ///
730 /// [`prctl(PR_PAC_RESET_KEYS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
731 #[inline]
reset_pointer_authentication_keys( keys: Option<PointerAuthenticationKeys>, ) -> io::Result<()>732 pub unsafe fn reset_pointer_authentication_keys(
733 keys: Option<PointerAuthenticationKeys>,
734 ) -> io::Result<()> {
735 let keys = keys.as_ref().map_or(0_u32, PointerAuthenticationKeys::bits);
736 prctl_2args(PR_PAC_RESET_KEYS, keys as usize as *mut _).map(|_r| ())
737 }
738
739 //
740 // PR_GET_TAGGED_ADDR_CTRL/PR_SET_TAGGED_ADDR_CTRL
741 //
742
743 const PR_GET_TAGGED_ADDR_CTRL: c_int = 56;
744
745 const PR_MTE_TAG_SHIFT: u32 = 3;
746 const PR_MTE_TAG_MASK: u32 = 0xffff_u32 << PR_MTE_TAG_SHIFT;
747
748 bitflags! {
749 /// Zero means addresses that are passed for the purpose of being
750 /// dereferenced by the kernel must be untagged.
751 #[repr(transparent)]
752 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
753 pub struct TaggedAddressMode: u32 {
754 /// Addresses that are passed for the purpose of being dereferenced by
755 /// the kernel may be tagged.
756 const ENABLED = 1_u32 << 0;
757 /// Synchronous tag check fault mode.
758 const TCF_SYNC = 1_u32 << 1;
759 /// Asynchronous tag check fault mode.
760 const TCF_ASYNC = 1_u32 << 2;
761
762 /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
763 const _ = !0;
764 }
765 }
766
767 /// Get the current tagged address mode for the calling thread.
768 ///
769 /// # References
770 /// - [`prctl(PR_GET_TAGGED_ADDR_CTRL,...)`]
771 ///
772 /// [`prctl(PR_GET_TAGGED_ADDR_CTRL,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
773 #[inline]
current_tagged_address_mode() -> io::Result<(Option<TaggedAddressMode>, u32)>774 pub fn current_tagged_address_mode() -> io::Result<(Option<TaggedAddressMode>, u32)> {
775 let r = unsafe { prctl_1arg(PR_GET_TAGGED_ADDR_CTRL)? } as c_uint;
776 let mode = r & 0b111_u32;
777 let mte_tag = (r & PR_MTE_TAG_MASK) >> PR_MTE_TAG_SHIFT;
778 Ok((TaggedAddressMode::from_bits(mode), mte_tag))
779 }
780
781 const PR_SET_TAGGED_ADDR_CTRL: c_int = 55;
782
783 /// Controls support for passing tagged user-space addresses to the kernel.
784 ///
785 /// # References
786 /// - [`prctl(PR_SET_TAGGED_ADDR_CTRL,...)`]
787 ///
788 /// # Safety
789 ///
790 /// Please ensure the conditions necessary to safely call this function, as
791 /// detailed in the references above.
792 ///
793 /// [`prctl(PR_SET_TAGGED_ADDR_CTRL,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
794 #[inline]
set_current_tagged_address_mode( mode: Option<TaggedAddressMode>, mte_tag: u32, ) -> io::Result<()>795 pub unsafe fn set_current_tagged_address_mode(
796 mode: Option<TaggedAddressMode>,
797 mte_tag: u32,
798 ) -> io::Result<()> {
799 let config = mode.as_ref().map_or(0_u32, TaggedAddressMode::bits)
800 | ((mte_tag << PR_MTE_TAG_SHIFT) & PR_MTE_TAG_MASK);
801 prctl_2args(PR_SET_TAGGED_ADDR_CTRL, config as usize as *mut _).map(|_r| ())
802 }
803
804 //
805 // PR_SET_SYSCALL_USER_DISPATCH
806 //
807
808 const PR_SET_SYSCALL_USER_DISPATCH: c_int = 59;
809
810 const PR_SYS_DISPATCH_OFF: usize = 0;
811
812 /// Disable Syscall User Dispatch mechanism.
813 ///
814 /// # References
815 /// - [`prctl(PR_SET_SYSCALL_USER_DISPATCH,PR_SYS_DISPATCH_OFF,...)`]
816 ///
817 /// # Safety
818 ///
819 /// Please ensure the conditions necessary to safely call this function, as
820 /// detailed in the references above.
821 ///
822 /// [`prctl(PR_SET_SYSCALL_USER_DISPATCH,PR_SYS_DISPATCH_OFF,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
823 #[inline]
disable_syscall_user_dispatch() -> io::Result<()>824 pub unsafe fn disable_syscall_user_dispatch() -> io::Result<()> {
825 prctl_2args(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_OFF as *mut _).map(|_r| ())
826 }
827
828 const PR_SYS_DISPATCH_ON: usize = 1;
829
830 /// Allow system calls to be executed.
831 const SYSCALL_DISPATCH_FILTER_ALLOW: u8 = 0;
832 /// Block system calls from executing.
833 const SYSCALL_DISPATCH_FILTER_BLOCK: u8 = 1;
834
835 /// Value of the fast switch flag controlling system calls user dispatch
836 /// mechanism without the need to issue a syscall.
837 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
838 #[repr(u8)]
839 pub enum SysCallUserDispatchFastSwitch {
840 /// System calls are allowed to execute.
841 Allow = SYSCALL_DISPATCH_FILTER_ALLOW,
842 /// System calls are blocked from executing.
843 Block = SYSCALL_DISPATCH_FILTER_BLOCK,
844 }
845
846 impl TryFrom<u8> for SysCallUserDispatchFastSwitch {
847 type Error = io::Errno;
848
try_from(value: u8) -> Result<Self, Self::Error>849 fn try_from(value: u8) -> Result<Self, Self::Error> {
850 match value {
851 SYSCALL_DISPATCH_FILTER_ALLOW => Ok(Self::Allow),
852 SYSCALL_DISPATCH_FILTER_BLOCK => Ok(Self::Block),
853 _ => Err(io::Errno::RANGE),
854 }
855 }
856 }
857
858 /// Enable Syscall User Dispatch mechanism.
859 ///
860 /// # References
861 /// - [`prctl(PR_SET_SYSCALL_USER_DISPATCH,PR_SYS_DISPATCH_ON,...)`]
862 ///
863 /// # Safety
864 ///
865 /// Please ensure the conditions necessary to safely call this function, as
866 /// detailed in the references above.
867 ///
868 /// [`prctl(PR_SET_SYSCALL_USER_DISPATCH,PR_SYS_DISPATCH_ON,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
869 #[inline]
enable_syscall_user_dispatch( always_allowed_region: &[u8], fast_switch_flag: &AtomicU8, ) -> io::Result<()>870 pub unsafe fn enable_syscall_user_dispatch(
871 always_allowed_region: &[u8],
872 fast_switch_flag: &AtomicU8,
873 ) -> io::Result<()> {
874 syscalls::prctl(
875 PR_SET_SYSCALL_USER_DISPATCH,
876 PR_SYS_DISPATCH_ON as *mut _,
877 always_allowed_region.as_ptr() as *mut _,
878 always_allowed_region.len() as *mut _,
879 as_ptr(fast_switch_flag) as *mut _,
880 )
881 .map(|_r| ())
882 }
883
884 //
885 // PR_SCHED_CORE
886 //
887
888 const PR_SCHED_CORE: c_int = 62;
889
890 const PR_SCHED_CORE_GET: usize = 0;
891
892 const PR_SCHED_CORE_SCOPE_THREAD: u32 = 0;
893 const PR_SCHED_CORE_SCOPE_THREAD_GROUP: u32 = 1;
894 const PR_SCHED_CORE_SCOPE_PROCESS_GROUP: u32 = 2;
895
896 /// `PR_SCHED_CORE_SCOPE_*`.
897 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
898 #[repr(u32)]
899 pub enum CoreSchedulingScope {
900 /// Operation will be performed for the thread.
901 Thread = PR_SCHED_CORE_SCOPE_THREAD,
902 /// Operation will be performed for all tasks in the task group of the
903 /// process.
904 ThreadGroup = PR_SCHED_CORE_SCOPE_THREAD_GROUP,
905 /// Operation will be performed for all processes in the process group.
906 ProcessGroup = PR_SCHED_CORE_SCOPE_PROCESS_GROUP,
907 }
908
909 impl TryFrom<u32> for CoreSchedulingScope {
910 type Error = io::Errno;
911
try_from(value: u32) -> Result<Self, Self::Error>912 fn try_from(value: u32) -> Result<Self, Self::Error> {
913 match value {
914 PR_SCHED_CORE_SCOPE_THREAD => Ok(Self::Thread),
915 PR_SCHED_CORE_SCOPE_THREAD_GROUP => Ok(Self::ThreadGroup),
916 PR_SCHED_CORE_SCOPE_PROCESS_GROUP => Ok(Self::ProcessGroup),
917 _ => Err(io::Errno::RANGE),
918 }
919 }
920 }
921
922 /// Get core scheduling cookie of a process.
923 ///
924 /// # References
925 /// - [`prctl(PR_SCHED_CORE,PR_SCHED_CORE_GET,...)`]
926 ///
927 /// [`prctl(PR_SCHED_CORE,PR_SCHED_CORE_GET,...)`]: https://www.kernel.org/doc/html/v5.18/admin-guide/hw-vuln/core-scheduling.html
928 #[inline]
core_scheduling_cookie(pid: Pid, scope: CoreSchedulingScope) -> io::Result<u64>929 pub fn core_scheduling_cookie(pid: Pid, scope: CoreSchedulingScope) -> io::Result<u64> {
930 let mut value: MaybeUninit<u64> = MaybeUninit::uninit();
931 unsafe {
932 syscalls::prctl(
933 PR_SCHED_CORE,
934 PR_SCHED_CORE_GET as *mut _,
935 pid.as_raw_nonzero().get() as usize as *mut _,
936 scope as usize as *mut _,
937 value.as_mut_ptr().cast(),
938 )?;
939 Ok(value.assume_init())
940 }
941 }
942
943 const PR_SCHED_CORE_CREATE: usize = 1;
944
945 /// Create unique core scheduling cookie.
946 ///
947 /// # References
948 /// - [`prctl(PR_SCHED_CORE,PR_SCHED_CORE_CREATE,...)`]
949 ///
950 /// [`prctl(PR_SCHED_CORE,PR_SCHED_CORE_CREATE,...)`]: https://www.kernel.org/doc/html/v5.18/admin-guide/hw-vuln/core-scheduling.html
951 #[inline]
create_core_scheduling_cookie(pid: Pid, scope: CoreSchedulingScope) -> io::Result<()>952 pub fn create_core_scheduling_cookie(pid: Pid, scope: CoreSchedulingScope) -> io::Result<()> {
953 unsafe {
954 syscalls::prctl(
955 PR_SCHED_CORE,
956 PR_SCHED_CORE_CREATE as *mut _,
957 pid.as_raw_nonzero().get() as usize as *mut _,
958 scope as usize as *mut _,
959 ptr::null_mut(),
960 )
961 .map(|_r| ())
962 }
963 }
964
965 const PR_SCHED_CORE_SHARE_TO: usize = 2;
966
967 /// Push core scheduling cookie to a process.
968 ///
969 /// # References
970 /// - [`prctl(PR_SCHED_CORE,PR_SCHED_CORE_SHARE_TO,...)`]
971 ///
972 /// [`prctl(PR_SCHED_CORE,PR_SCHED_CORE_SHARE_TO,...)`]: https://www.kernel.org/doc/html/v5.18/admin-guide/hw-vuln/core-scheduling.html
973 #[inline]
push_core_scheduling_cookie(pid: Pid, scope: CoreSchedulingScope) -> io::Result<()>974 pub fn push_core_scheduling_cookie(pid: Pid, scope: CoreSchedulingScope) -> io::Result<()> {
975 unsafe {
976 syscalls::prctl(
977 PR_SCHED_CORE,
978 PR_SCHED_CORE_SHARE_TO as *mut _,
979 pid.as_raw_nonzero().get() as usize as *mut _,
980 scope as usize as *mut _,
981 ptr::null_mut(),
982 )
983 .map(|_r| ())
984 }
985 }
986
987 const PR_SCHED_CORE_SHARE_FROM: usize = 3;
988
989 /// Pull core scheduling cookie from a process.
990 ///
991 /// # References
992 /// - [`prctl(PR_SCHED_CORE,PR_SCHED_CORE_SHARE_FROM,...)`]
993 ///
994 /// [`prctl(PR_SCHED_CORE,PR_SCHED_CORE_SHARE_FROM,...)`]: https://www.kernel.org/doc/html/v5.18/admin-guide/hw-vuln/core-scheduling.html
995 #[inline]
pull_core_scheduling_cookie(pid: Pid, scope: CoreSchedulingScope) -> io::Result<()>996 pub fn pull_core_scheduling_cookie(pid: Pid, scope: CoreSchedulingScope) -> io::Result<()> {
997 unsafe {
998 syscalls::prctl(
999 PR_SCHED_CORE,
1000 PR_SCHED_CORE_SHARE_FROM as *mut _,
1001 pid.as_raw_nonzero().get() as usize as *mut _,
1002 scope as usize as *mut _,
1003 ptr::null_mut(),
1004 )
1005 .map(|_r| ())
1006 }
1007 }
1008