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