use bitflags::bitflags;
use core::mem::MaybeUninit;
use crate::pid::Pid;
use crate::{backend, io};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct CapabilitySets {
pub effective: CapabilityFlags,
pub permitted: CapabilityFlags,
pub inheritable: CapabilityFlags,
}
bitflags! {
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct CapabilityFlags: u64 {
const CHOWN = 1 << linux_raw_sys::general::CAP_CHOWN;
const DAC_OVERRIDE = 1 << linux_raw_sys::general::CAP_DAC_OVERRIDE;
const DAC_READ_SEARCH = 1 << linux_raw_sys::general::CAP_DAC_READ_SEARCH;
const FOWNER = 1 << linux_raw_sys::general::CAP_FOWNER;
const FSETID = 1 << linux_raw_sys::general::CAP_FSETID;
const KILL = 1 << linux_raw_sys::general::CAP_KILL;
const SETGID = 1 << linux_raw_sys::general::CAP_SETGID;
const SETUID = 1 << linux_raw_sys::general::CAP_SETUID;
const SETPCAP = 1 << linux_raw_sys::general::CAP_SETPCAP;
const LINUX_IMMUTABLE = 1 << linux_raw_sys::general::CAP_LINUX_IMMUTABLE;
const NET_BIND_SERVICE = 1 << linux_raw_sys::general::CAP_NET_BIND_SERVICE;
const NET_BROADCAST = 1 << linux_raw_sys::general::CAP_NET_BROADCAST;
const NET_ADMIN = 1 << linux_raw_sys::general::CAP_NET_ADMIN;
const NET_RAW = 1 << linux_raw_sys::general::CAP_NET_RAW;
const IPC_LOCK = 1 << linux_raw_sys::general::CAP_IPC_LOCK;
const IPC_OWNER = 1 << linux_raw_sys::general::CAP_IPC_OWNER;
const SYS_MODULE = 1 << linux_raw_sys::general::CAP_SYS_MODULE;
const SYS_RAWIO = 1 << linux_raw_sys::general::CAP_SYS_RAWIO;
const SYS_CHROOT = 1 << linux_raw_sys::general::CAP_SYS_CHROOT;
const SYS_PTRACE = 1 << linux_raw_sys::general::CAP_SYS_PTRACE;
const SYS_PACCT = 1 << linux_raw_sys::general::CAP_SYS_PACCT;
const SYS_ADMIN = 1 << linux_raw_sys::general::CAP_SYS_ADMIN;
const SYS_BOOT = 1 << linux_raw_sys::general::CAP_SYS_BOOT;
const SYS_NICE = 1 << linux_raw_sys::general::CAP_SYS_NICE;
const SYS_RESOURCE = 1 << linux_raw_sys::general::CAP_SYS_RESOURCE;
const SYS_TIME = 1 << linux_raw_sys::general::CAP_SYS_TIME;
const SYS_TTY_CONFIG = 1 << linux_raw_sys::general::CAP_SYS_TTY_CONFIG;
const MKNOD = 1 << linux_raw_sys::general::CAP_MKNOD;
const LEASE = 1 << linux_raw_sys::general::CAP_LEASE;
const AUDIT_WRITE = 1 << linux_raw_sys::general::CAP_AUDIT_WRITE;
const AUDIT_CONTROL = 1 << linux_raw_sys::general::CAP_AUDIT_CONTROL;
const SETFCAP = 1 << linux_raw_sys::general::CAP_SETFCAP;
const MAC_OVERRIDE = 1 << linux_raw_sys::general::CAP_MAC_OVERRIDE;
const MAC_ADMIN = 1 << linux_raw_sys::general::CAP_MAC_ADMIN;
const SYSLOG = 1 << linux_raw_sys::general::CAP_SYSLOG;
const WAKE_ALARM = 1 << linux_raw_sys::general::CAP_WAKE_ALARM;
const BLOCK_SUSPEND = 1 << linux_raw_sys::general::CAP_BLOCK_SUSPEND;
const AUDIT_READ = 1 << linux_raw_sys::general::CAP_AUDIT_READ;
const PERFMON = 1 << linux_raw_sys::general::CAP_PERFMON;
const BPF = 1 << linux_raw_sys::general::CAP_BPF;
const CHECKPOINT_RESTORE = 1 << linux_raw_sys::general::CAP_CHECKPOINT_RESTORE;
const _ = !0;
}
}
#[inline]
#[doc(alias = "capget")]
pub fn capabilities(pid: Option<Pid>) -> io::Result<CapabilitySets> {
capget(pid)
}
#[inline]
#[doc(alias = "capset")]
pub fn set_capabilities(pid: Option<Pid>, sets: CapabilitySets) -> io::Result<()> {
capset(pid, sets)
}
#[inline]
#[allow(unsafe_code)]
fn capget(pid: Option<Pid>) -> io::Result<CapabilitySets> {
let mut data = [MaybeUninit::<linux_raw_sys::general::__user_cap_data_struct>::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)?;
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);
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<Pid>, 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)
}