Skip to main content

kernel_explainer/
capabilities.rs

1// Capability set → human descriptions.
2//
3// Mirrors the decoding logic previously implemented in
4// `peek-core::proc::kernel::decode_caps`, but works on the numeric bitset
5// directly instead of the raw hex string.
6
7const CAP_NAMES: &[&str] = &[
8    "CHOWN",
9    "DAC_OVERRIDE",
10    "DAC_READ_SEARCH",
11    "FOWNER",
12    "FSETID",
13    "KILL",
14    "SETGID",
15    "SETUID",
16    "SETPCAP",
17    "LINUX_IMMUTABLE",
18    "NET_BIND_SERVICE",
19    "NET_BROADCAST",
20    "NET_ADMIN",
21    "NET_RAW",
22    "IPC_LOCK",
23    "IPC_OWNER",
24    "SYS_MODULE",
25    "SYS_RAWIO",
26    "SYS_CHROOT",
27    "SYS_PTRACE",
28    "SYS_PACCT",
29    "SYS_ADMIN",
30    "SYS_BOOT",
31    "SYS_NICE",
32    "SYS_RESOURCE",
33    "SYS_TIME",
34    "SYS_TTY_CONFIG",
35    "MKNOD",
36    "LEASE",
37    "AUDIT_WRITE",
38    "AUDIT_CONTROL",
39    "SETFCAP",
40    "MAC_OVERRIDE",
41    "MAC_ADMIN",
42    "SYSLOG",
43    "WAKE_ALARM",
44    "BLOCK_SUSPEND",
45    "AUDIT_READ",
46    "PERFMON",
47    "BPF",
48    "CHECKPOINT_RESTORE",
49];
50
51fn caps_to_string(val: u64) -> String {
52    if val == 0 {
53        return "none".to_string();
54    }
55
56    let caps: Vec<&str> = CAP_NAMES
57        .iter()
58        .enumerate()
59        .filter(|(i, _)| val & (1u64 << i) != 0)
60        .map(|(_, name)| *name)
61        .collect();
62
63    if caps.is_empty() {
64        // Fall back to raw value if no names were found.
65        format!("{:#x}", val)
66    } else {
67        caps.join(", ")
68    }
69}
70
71/// Given the permitted and effective capability bitmasks, return
72/// human-readable descriptions for each set.
73pub fn format_caps(permitted: u64, effective: u64) -> (String, String) {
74    (caps_to_string(permitted), caps_to_string(effective))
75}