rustix/thread/
libcap.rs

1use bitflags::bitflags;
2use core::mem::MaybeUninit;
3
4use crate::pid::Pid;
5use crate::{backend, io};
6
7/// `__user_cap_data_struct`
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub struct CapabilitySets {
10    /// `__user_cap_data_struct.effective`
11    pub effective: CapabilitySet,
12    /// `__user_cap_data_struct.permitted`
13    pub permitted: CapabilitySet,
14    /// `__user_cap_data_struct.inheritable`
15    pub inheritable: CapabilitySet,
16}
17
18/// Previous name of `CapabilitySet`.
19#[deprecated(since = "1.1.0", note = "Renamed to CapabilitySet")]
20pub type CapabilityFlags = CapabilitySet;
21
22bitflags! {
23    /// `CAP_*` constants.
24    #[repr(transparent)]
25    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
26    pub struct CapabilitySet: u64 {
27        /// `CAP_CHOWN`
28        const CHOWN = 1 << linux_raw_sys::general::CAP_CHOWN;
29        /// `CAP_DAC_OVERRIDE`
30        const DAC_OVERRIDE = 1 << linux_raw_sys::general::CAP_DAC_OVERRIDE;
31        /// `CAP_DAC_READ_SEARCH`
32        const DAC_READ_SEARCH = 1 << linux_raw_sys::general::CAP_DAC_READ_SEARCH;
33        /// `CAP_FOWNER`
34        const FOWNER = 1 << linux_raw_sys::general::CAP_FOWNER;
35        /// `CAP_FSETID`
36        const FSETID = 1 << linux_raw_sys::general::CAP_FSETID;
37        /// `CAP_KILL`
38        const KILL = 1 << linux_raw_sys::general::CAP_KILL;
39        /// `CAP_SETGID`
40        const SETGID = 1 << linux_raw_sys::general::CAP_SETGID;
41        /// `CAP_SETUID`
42        const SETUID = 1 << linux_raw_sys::general::CAP_SETUID;
43        /// `CAP_SETPCAP`
44        const SETPCAP = 1 << linux_raw_sys::general::CAP_SETPCAP;
45        /// `CAP_LINUX_IMMUTABLE`
46        const LINUX_IMMUTABLE = 1 << linux_raw_sys::general::CAP_LINUX_IMMUTABLE;
47        /// `CAP_NET_BIND_SERVICE`
48        const NET_BIND_SERVICE = 1 << linux_raw_sys::general::CAP_NET_BIND_SERVICE;
49        /// `CAP_NET_BROADCAST`
50        const NET_BROADCAST = 1 << linux_raw_sys::general::CAP_NET_BROADCAST;
51        /// `CAP_NET_ADMIN`
52        const NET_ADMIN = 1 << linux_raw_sys::general::CAP_NET_ADMIN;
53        /// `CAP_NET_RAW`
54        const NET_RAW = 1 << linux_raw_sys::general::CAP_NET_RAW;
55        /// `CAP_IPC_LOCK`
56        const IPC_LOCK = 1 << linux_raw_sys::general::CAP_IPC_LOCK;
57        /// `CAP_IPC_OWNER`
58        const IPC_OWNER = 1 << linux_raw_sys::general::CAP_IPC_OWNER;
59        /// `CAP_SYS_MODULE`
60        const SYS_MODULE = 1 << linux_raw_sys::general::CAP_SYS_MODULE;
61        /// `CAP_SYS_RAWIO`
62        const SYS_RAWIO = 1 << linux_raw_sys::general::CAP_SYS_RAWIO;
63        /// `CAP_SYS_CHROOT`
64        const SYS_CHROOT = 1 << linux_raw_sys::general::CAP_SYS_CHROOT;
65        /// `CAP_SYS_PTRACE`
66        const SYS_PTRACE = 1 << linux_raw_sys::general::CAP_SYS_PTRACE;
67        /// `CAP_SYS_PACCT`
68        const SYS_PACCT = 1 << linux_raw_sys::general::CAP_SYS_PACCT;
69        /// `CAP_SYS_ADMIN`
70        const SYS_ADMIN = 1 << linux_raw_sys::general::CAP_SYS_ADMIN;
71        /// `CAP_SYS_BOOT`
72        const SYS_BOOT = 1 << linux_raw_sys::general::CAP_SYS_BOOT;
73        /// `CAP_SYS_NICE`
74        const SYS_NICE = 1 << linux_raw_sys::general::CAP_SYS_NICE;
75        /// `CAP_SYS_RESOURCE`
76        const SYS_RESOURCE = 1 << linux_raw_sys::general::CAP_SYS_RESOURCE;
77        /// `CAP_SYS_TIME`
78        const SYS_TIME = 1 << linux_raw_sys::general::CAP_SYS_TIME;
79        /// `CAP_SYS_TTY_CONFIG`
80        const SYS_TTY_CONFIG = 1 << linux_raw_sys::general::CAP_SYS_TTY_CONFIG;
81        /// `CAP_MKNOD`
82        const MKNOD = 1 << linux_raw_sys::general::CAP_MKNOD;
83        /// `CAP_LEASE`
84        const LEASE = 1 << linux_raw_sys::general::CAP_LEASE;
85        /// `CAP_AUDIT_WRITE`
86        const AUDIT_WRITE = 1 << linux_raw_sys::general::CAP_AUDIT_WRITE;
87        /// `CAP_AUDIT_CONTROL`
88        const AUDIT_CONTROL = 1 << linux_raw_sys::general::CAP_AUDIT_CONTROL;
89        /// `CAP_SETFCAP`
90        const SETFCAP = 1 << linux_raw_sys::general::CAP_SETFCAP;
91        /// `CAP_MAC_OVERRIDE`
92        const MAC_OVERRIDE = 1 << linux_raw_sys::general::CAP_MAC_OVERRIDE;
93        /// `CAP_MAC_ADMIN`
94        const MAC_ADMIN = 1 << linux_raw_sys::general::CAP_MAC_ADMIN;
95        /// `CAP_SYSLOG`
96        const SYSLOG = 1 << linux_raw_sys::general::CAP_SYSLOG;
97        /// `CAP_WAKE_ALARM`
98        const WAKE_ALARM = 1 << linux_raw_sys::general::CAP_WAKE_ALARM;
99        /// `CAP_BLOCK_SUSPEND`
100        const BLOCK_SUSPEND = 1 << linux_raw_sys::general::CAP_BLOCK_SUSPEND;
101        /// `CAP_AUDIT_READ`
102        const AUDIT_READ = 1 << linux_raw_sys::general::CAP_AUDIT_READ;
103        /// `CAP_PERFMON`
104        const PERFMON = 1 << linux_raw_sys::general::CAP_PERFMON;
105        /// `CAP_BPF`
106        const BPF = 1 << linux_raw_sys::general::CAP_BPF;
107        /// `CAP_CHECKPOINT_RESTORE`
108        const CHECKPOINT_RESTORE = 1 << linux_raw_sys::general::CAP_CHECKPOINT_RESTORE;
109
110        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
111        const _ = !0;
112    }
113}
114
115/// `capget(_LINUX_CAPABILITY_VERSION_3, pid)`
116///
117/// # References
118///  - [Linux]
119///
120/// [Linux]: https://man7.org/linux/man-pages/man2/capget.2.html
121#[inline]
122#[doc(alias = "capget")]
123pub fn capabilities(pid: Option<Pid>) -> io::Result<CapabilitySets> {
124    capget(pid)
125}
126
127/// `capset(_LINUX_CAPABILITY_VERSION_3, pid, effective, permitted,
128/// inheritable)`
129///
130/// # References
131///  - [Linux]
132///
133/// [Linux]: https://man7.org/linux/man-pages/man2/capget.2.html
134#[inline]
135#[doc(alias = "capset")]
136pub fn set_capabilities(pid: Option<Pid>, sets: CapabilitySets) -> io::Result<()> {
137    capset(pid, sets)
138}
139
140#[inline]
141#[allow(unsafe_code)]
142fn capget(pid: Option<Pid>) -> io::Result<CapabilitySets> {
143    let mut data = [MaybeUninit::<linux_raw_sys::general::__user_cap_data_struct>::uninit(); 2];
144
145    let data = {
146        let mut header = linux_raw_sys::general::__user_cap_header_struct {
147            version: linux_raw_sys::general::_LINUX_CAPABILITY_VERSION_3,
148            pid: Pid::as_raw(pid) as backend::c::c_int,
149        };
150
151        backend::thread::syscalls::capget(&mut header, &mut data)?;
152        // SAFETY: v3 is a 64-bit implementation, so the kernel filled in both
153        // data structs.
154        unsafe { (data[0].assume_init(), data[1].assume_init()) }
155    };
156
157    let effective = u64::from(data.0.effective) | (u64::from(data.1.effective) << u32::BITS);
158    let permitted = u64::from(data.0.permitted) | (u64::from(data.1.permitted) << u32::BITS);
159    let inheritable = u64::from(data.0.inheritable) | (u64::from(data.1.inheritable) << u32::BITS);
160
161    // The kernel returns a partitioned bitset that we just combined above.
162    Ok(CapabilitySets {
163        effective: CapabilitySet::from_bits_retain(effective),
164        permitted: CapabilitySet::from_bits_retain(permitted),
165        inheritable: CapabilitySet::from_bits_retain(inheritable),
166    })
167}
168
169#[inline]
170fn capset(pid: Option<Pid>, sets: CapabilitySets) -> io::Result<()> {
171    let mut header = linux_raw_sys::general::__user_cap_header_struct {
172        version: linux_raw_sys::general::_LINUX_CAPABILITY_VERSION_3,
173        pid: Pid::as_raw(pid) as backend::c::c_int,
174    };
175    let data = [
176        linux_raw_sys::general::__user_cap_data_struct {
177            effective: sets.effective.bits() as u32,
178            permitted: sets.permitted.bits() as u32,
179            inheritable: sets.inheritable.bits() as u32,
180        },
181        linux_raw_sys::general::__user_cap_data_struct {
182            effective: (sets.effective.bits() >> u32::BITS) as u32,
183            permitted: (sets.permitted.bits() >> u32::BITS) as u32,
184            inheritable: (sets.inheritable.bits() >> u32::BITS) as u32,
185        },
186    ];
187
188    backend::thread::syscalls::capset(&mut header, &data)
189}