Files
moss-kernel/libkernel/src/proc/caps.rs
2025-12-29 13:53:02 -08:00

166 lines
5.0 KiB
Rust

use crate::error::{KernelError, Result};
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct CapabilitiesFlags: u64 {
const CAP_CHOWN = 1 << 0;
const CAP_DAC_OVERRIDE = 1 << 1;
const CAP_DAC_READ_SEARCH = 1 << 2;
const CAP_FOWNER = 1 << 3;
const CAP_FSETID = 1 << 4;
const CAP_KILL = 1 << 5;
const CAP_SETGID = 1 << 6;
const CAP_SETUID = 1 << 7;
const CAP_SETPCAP = 1 << 8;
const CAP_LINUX_IMMUTABLE = 1 << 9;
const CAP_NET_BIND_SERVICE = 1 << 10;
const CAP_NET_BROADCAST = 1 << 11;
const CAP_NET_ADMIN = 1 << 12;
const CAP_NET_RAW = 1 << 13;
const CAP_IPC_LOCK = 1 << 14;
const CAP_IPC_OWNER = 1 << 15;
const CAP_SYS_MODULE = 1 << 16;
const CAP_SYS_RAWIO = 1 << 17;
const CAP_SYS_CHROOT = 1 << 18;
const CAP_SYS_PTRACE = 1 << 19;
const CAP_SYS_PACCT = 1 << 20;
const CAP_SYS_ADMIN = 1 << 21;
const CAP_SYS_BOOT = 1 << 22;
const CAP_SYS_NICE = 1 << 23;
const CAP_SYS_RESOURCE = 1 << 24;
const CAP_SYS_TIME = 1 << 25;
const CAP_SYS_TTY_CONFIG = 1 << 26;
const CAP_MKNOD = 1 << 27;
const CAP_LEASE = 1 << 28;
const CAP_AUDIT_WRITE = 1 << 29;
const CAP_AUDIT_CONTROL = 1 << 30;
const CAP_SETFCAP = 1 << 31;
const CAP_MAC_OVERRIDE = 1 << 32;
const CAP_MAC_ADMIN = 1 << 33;
const CAP_SYSLOG = 1 << 34;
const CAP_WAKE_ALARM = 1 << 35;
const CAP_BLOCK_SUSPEND = 1 << 36;
const CAP_AUDIT_READ = 1 << 37;
const CAP_PERFMON = 1 << 38;
const CAP_BPF = 1 << 39;
const CAP_CHECKPOINT_RESTORE = 1 << 40;
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Capabilities {
effective: CapabilitiesFlags,
permitted: CapabilitiesFlags,
inheritable: CapabilitiesFlags,
ambient: CapabilitiesFlags,
bounding: CapabilitiesFlags,
}
impl Capabilities {
pub fn new(
effective: CapabilitiesFlags,
permitted: CapabilitiesFlags,
inheritable: CapabilitiesFlags,
ambient: CapabilitiesFlags,
bounding: CapabilitiesFlags,
) -> Self {
Self {
effective,
permitted,
inheritable,
ambient,
bounding,
}
}
pub fn new_root() -> Self {
Self {
effective: CapabilitiesFlags::all(),
permitted: CapabilitiesFlags::all(),
inheritable: CapabilitiesFlags::all(),
ambient: CapabilitiesFlags::all(),
bounding: CapabilitiesFlags::all(),
}
}
pub fn new_empty() -> Self {
Self {
effective: CapabilitiesFlags::empty(),
permitted: CapabilitiesFlags::empty(),
inheritable: CapabilitiesFlags::empty(),
ambient: CapabilitiesFlags::empty(),
bounding: CapabilitiesFlags::empty(),
}
}
/// Convenience method for creating capabilities with a single capability
pub fn new_cap(cap: CapabilitiesFlags) -> Self {
Self {
effective: cap,
permitted: cap,
inheritable: cap,
ambient: cap,
bounding: cap,
}
}
/// Set the publicly mutable fields on capabilities
pub fn set_public(
&mut self,
caller_caps: Capabilities,
effective: CapabilitiesFlags,
permitted: CapabilitiesFlags,
inheritable: CapabilitiesFlags,
) -> Result<()> {
// permitted should be a subset of self.permitted, and effective should be a subset of permitted
// inheritable should be a subset of self.bounding, or caller's effective should contain CAP_SETPCAP
if !self.permitted.contains(permitted)
|| !permitted.contains(effective)
|| (!self.bounding.contains(inheritable)
&& !caller_caps
.effective
.contains(CapabilitiesFlags::CAP_SETPCAP))
{
return Err(KernelError::NotPermitted);
}
self.effective = effective;
self.permitted = permitted;
self.inheritable = inheritable;
Ok(())
}
pub fn effective(&self) -> CapabilitiesFlags {
self.effective
}
pub fn permitted(&self) -> CapabilitiesFlags {
self.permitted
}
pub fn inheritable(&self) -> CapabilitiesFlags {
self.inheritable
}
pub fn ambient(&self) -> CapabilitiesFlags {
self.ambient
}
pub fn bounding(&self) -> CapabilitiesFlags {
self.bounding
}
/// Checks if a capability is effective, as in if it can be used.
pub fn is_capable(&self, cap: CapabilitiesFlags) -> bool {
self.effective.contains(cap)
}
/// Shortcut for returning EPERM if a capability is not effective.
pub fn check_capable(&self, cap: CapabilitiesFlags) -> Result<()> {
if !self.effective.contains(cap) {
Err(KernelError::NotPermitted)
} else {
Ok(())
}
}
}