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