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" )] |
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" )] |
132 | pub fn set_capabilities(pid: Option<Pid>, sets: CapabilitySets) -> io::Result<()> { |
133 | capset(pid, sets) |
134 | } |
135 | |
136 | #[inline ] |
137 | #[allow (unsafe_code)] |
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 ] |
166 | fn capset(pid: Option<Pid>, sets: CapabilitySets) -> io::Result<()> { |
167 | let mut header: __user_cap_header_struct = 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: [__user_cap_data_struct; 2] = [ |
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 | |