use bitflags::bitflags; use core::mem::MaybeUninit; use crate::pid::Pid; use crate::{backend, io}; /// `__user_cap_data_struct` #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct CapabilitySets { /// `__user_cap_data_struct.effective` pub effective: CapabilityFlags, /// `__user_cap_data_struct.permitted` pub permitted: CapabilityFlags, /// `__user_cap_data_struct.inheritable` pub inheritable: CapabilityFlags, } bitflags! { /// `CAP_*` constants. #[repr(transparent)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct CapabilityFlags: u64 { /// `CAP_CHOWN` const CHOWN = 1 << linux_raw_sys::general::CAP_CHOWN; /// `CAP_DAC_OVERRIDE` const DAC_OVERRIDE = 1 << linux_raw_sys::general::CAP_DAC_OVERRIDE; /// `CAP_DAC_READ_SEARCH` const DAC_READ_SEARCH = 1 << linux_raw_sys::general::CAP_DAC_READ_SEARCH; /// `CAP_FOWNER` const FOWNER = 1 << linux_raw_sys::general::CAP_FOWNER; /// `CAP_FSETID` const FSETID = 1 << linux_raw_sys::general::CAP_FSETID; /// `CAP_KILL` const KILL = 1 << linux_raw_sys::general::CAP_KILL; /// `CAP_SETGID` const SETGID = 1 << linux_raw_sys::general::CAP_SETGID; /// `CAP_SETUID` const SETUID = 1 << linux_raw_sys::general::CAP_SETUID; /// `CAP_SETPCAP` const SETPCAP = 1 << linux_raw_sys::general::CAP_SETPCAP; /// `CAP_LINUX_IMMUTABLE` const LINUX_IMMUTABLE = 1 << linux_raw_sys::general::CAP_LINUX_IMMUTABLE; /// `CAP_NET_BIND_SERVICE` const NET_BIND_SERVICE = 1 << linux_raw_sys::general::CAP_NET_BIND_SERVICE; /// `CAP_NET_BROADCAST` const NET_BROADCAST = 1 << linux_raw_sys::general::CAP_NET_BROADCAST; /// `CAP_NET_ADMIN` const NET_ADMIN = 1 << linux_raw_sys::general::CAP_NET_ADMIN; /// `CAP_NET_RAW` const NET_RAW = 1 << linux_raw_sys::general::CAP_NET_RAW; /// `CAP_IPC_LOCK` const IPC_LOCK = 1 << linux_raw_sys::general::CAP_IPC_LOCK; /// `CAP_IPC_OWNER` const IPC_OWNER = 1 << linux_raw_sys::general::CAP_IPC_OWNER; /// `CAP_SYS_MODULE` const SYS_MODULE = 1 << linux_raw_sys::general::CAP_SYS_MODULE; /// `CAP_SYS_RAWIO` const SYS_RAWIO = 1 << linux_raw_sys::general::CAP_SYS_RAWIO; /// `CAP_SYS_CHROOT` const SYS_CHROOT = 1 << linux_raw_sys::general::CAP_SYS_CHROOT; /// `CAP_SYS_PTRACE` const SYS_PTRACE = 1 << linux_raw_sys::general::CAP_SYS_PTRACE; /// `CAP_SYS_PACCT` const SYS_PACCT = 1 << linux_raw_sys::general::CAP_SYS_PACCT; /// `CAP_SYS_ADMIN` const SYS_ADMIN = 1 << linux_raw_sys::general::CAP_SYS_ADMIN; /// `CAP_SYS_BOOT` const SYS_BOOT = 1 << linux_raw_sys::general::CAP_SYS_BOOT; /// `CAP_SYS_NICE` const SYS_NICE = 1 << linux_raw_sys::general::CAP_SYS_NICE; /// `CAP_SYS_RESOURCE` const SYS_RESOURCE = 1 << linux_raw_sys::general::CAP_SYS_RESOURCE; /// `CAP_SYS_TIME` const SYS_TIME = 1 << linux_raw_sys::general::CAP_SYS_TIME; /// `CAP_SYS_TTY_CONFIG` const SYS_TTY_CONFIG = 1 << linux_raw_sys::general::CAP_SYS_TTY_CONFIG; /// `CAP_MKNOD` const MKNOD = 1 << linux_raw_sys::general::CAP_MKNOD; /// `CAP_LEASE` const LEASE = 1 << linux_raw_sys::general::CAP_LEASE; /// `CAP_AUDIT_WRITE` const AUDIT_WRITE = 1 << linux_raw_sys::general::CAP_AUDIT_WRITE; /// `CAP_AUDIT_CONTROL` const AUDIT_CONTROL = 1 << linux_raw_sys::general::CAP_AUDIT_CONTROL; /// `CAP_SETFCAP` const SETFCAP = 1 << linux_raw_sys::general::CAP_SETFCAP; /// `CAP_MAC_OVERRIDE` const MAC_OVERRIDE = 1 << linux_raw_sys::general::CAP_MAC_OVERRIDE; /// `CAP_MAC_ADMIN` const MAC_ADMIN = 1 << linux_raw_sys::general::CAP_MAC_ADMIN; /// `CAP_SYSLOG` const SYSLOG = 1 << linux_raw_sys::general::CAP_SYSLOG; /// `CAP_WAKE_ALARM` const WAKE_ALARM = 1 << linux_raw_sys::general::CAP_WAKE_ALARM; /// `CAP_BLOCK_SUSPEND` const BLOCK_SUSPEND = 1 << linux_raw_sys::general::CAP_BLOCK_SUSPEND; /// `CAP_AUDIT_READ` const AUDIT_READ = 1 << linux_raw_sys::general::CAP_AUDIT_READ; /// `CAP_PERFMON` const PERFMON = 1 << linux_raw_sys::general::CAP_PERFMON; /// `CAP_BPF` const BPF = 1 << linux_raw_sys::general::CAP_BPF; /// `CAP_CHECKPOINT_RESTORE` const CHECKPOINT_RESTORE = 1 << linux_raw_sys::general::CAP_CHECKPOINT_RESTORE; /// const _ = !0; } } /// `capget(_LINUX_CAPABILITY_VERSION_3, pid)` /// /// # References /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/capget.2.html #[inline] #[doc(alias = "capget")] pub fn capabilities(pid: Option) -> io::Result { capget(pid) } /// `capset(_LINUX_CAPABILITY_VERSION_3, pid, effective, permitted, /// inheritable)` /// /// # References /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/capget.2.html #[inline] #[doc(alias = "capset")] pub fn set_capabilities(pid: Option, sets: CapabilitySets) -> io::Result<()> { capset(pid, sets) } #[inline] #[allow(unsafe_code)] fn capget(pid: Option) -> io::Result { let mut data = [MaybeUninit::::uninit(); 2]; let data = { let mut header = linux_raw_sys::general::__user_cap_header_struct { version: linux_raw_sys::general::_LINUX_CAPABILITY_VERSION_3, pid: Pid::as_raw(pid) as backend::c::c_int, }; backend::thread::syscalls::capget(&mut header, &mut data)?; // SAFETY: v3 is a 64-bit implementation, so the kernel filled in both // data structs. unsafe { (data[0].assume_init(), data[1].assume_init()) } }; let effective = u64::from(data.0.effective) | (u64::from(data.1.effective) << u32::BITS); let permitted = u64::from(data.0.permitted) | (u64::from(data.1.permitted) << u32::BITS); let inheritable = u64::from(data.0.inheritable) | (u64::from(data.1.inheritable) << u32::BITS); // The kernel returns a partitioned bitset that we just combined above. Ok(CapabilitySets { effective: CapabilityFlags::from_bits_retain(effective), permitted: CapabilityFlags::from_bits_retain(permitted), inheritable: CapabilityFlags::from_bits_retain(inheritable), }) } #[inline] fn capset(pid: Option, sets: CapabilitySets) -> io::Result<()> { let mut header = linux_raw_sys::general::__user_cap_header_struct { version: linux_raw_sys::general::_LINUX_CAPABILITY_VERSION_3, pid: Pid::as_raw(pid) as backend::c::c_int, }; let data = [ linux_raw_sys::general::__user_cap_data_struct { effective: sets.effective.bits() as u32, permitted: sets.permitted.bits() as u32, inheritable: sets.inheritable.bits() as u32, }, linux_raw_sys::general::__user_cap_data_struct { effective: (sets.effective.bits() >> u32::BITS) as u32, permitted: (sets.permitted.bits() >> u32::BITS) as u32, inheritable: (sets.inheritable.bits() >> u32::BITS) as u32, }, ]; backend::thread::syscalls::capset(&mut header, &data) }