#![cfg(all(feature = "backend-linux", target_os = "linux"))]
use bvisor::linux::cgroup::{probe_controller_base, CgroupLeaf, CgroupLimits};
use std::io::Write;
use std::path::Path;
use std::process::Command;
use std::sync::atomic::{AtomicU64, Ordering};
static LEAF_COUNTER: AtomicU64 = AtomicU64::new(0);
const CAP: u64 = 4;
const FORK_ATTEMPTS: u32 = 30;
fn pids_events_max(leaf_dir: &Path) -> u64 {
let text = std::fs::read_to_string(leaf_dir.join("pids.events")).unwrap_or_default();
for line in text.lines() {
if let Some(rest) = line.strip_prefix("max ") {
return rest.trim().parse::<u64>().unwrap_or(0);
}
}
0
}
#[test]
fn pids_max_genuinely_denies_forks_past_the_cap_or_explicit_skip() {
let mut sink = std::io::stderr();
let Some(base) = probe_controller_base(&["pids"]) else {
let _ = writeln!(
sink,
"SKIP pids_max_genuinely_denies_forks: no writable `pids`-delegating cgroup v2 \
ancestor (probe_controller_base([\"pids\"]) == None) on this host"
);
return;
};
let _ = writeln!(
sink,
"REAL pids-delegating base at {}; running the live enforcement proof (cap={CAP})",
base.display()
);
let suffix = LEAF_COUNTER.fetch_add(1, Ordering::Relaxed);
let name = format!("bvisor-enforce-{}-{suffix}", std::process::id());
let mut leaf = match CgroupLeaf::create(&base, &name, CgroupLimits::with_pids_max(CAP)) {
Ok(leaf) => leaf,
Err(e) => {
let _ = writeln!(
sink,
"SKIP pids_max_genuinely_denies_forks: probe said delegated+writable but create \
failed ({e}); treating as no-delegation rather than a false failure"
);
return;
}
};
assert!(
leaf.setup().pids_enforced,
"a delegated+written pids limit must be honestly Enforced"
);
let dir = leaf.dir().expect("leaf dir").to_path_buf();
assert_eq!(
pids_events_max(&dir),
0,
"a fresh leaf has denied no forks yet"
);
let script = "echo $$ > \"$0/cgroup.procs\"; i=0; \
while [ $i -lt $1 ]; do sleep 30 & i=$((i+1)); done";
let status = Command::new("sh")
.arg("-c")
.arg(script)
.arg(&dir) .arg(FORK_ATTEMPTS.to_string()) .status();
let status = match status {
Ok(s) => s,
Err(e) => {
let _ = writeln!(
sink,
"SKIP pids_max_genuinely_denies_forks: cannot spawn sh ({e})"
);
let _ = leaf.kill();
let _ = leaf.remove();
return;
}
};
let _ = writeln!(
sink,
"workload shell exited with {status:?} (non-zero is expected once forks are denied)"
);
let denied = pids_events_max(&dir);
let current: u64 = std::fs::read_to_string(dir.join("pids.current"))
.ok()
.and_then(|t| t.trim().parse().ok())
.unwrap_or(u64::MAX);
let _ = writeln!(
sink,
"kernel-observed: pids.events max={denied} (forks denied), pids.current={current} (cap={CAP})"
);
let killed = leaf.kill();
let drained = leaf.wait_until_empty(50, std::time::Duration::from_millis(10));
let removed = leaf.remove();
assert!(
denied > 0,
"the kernel must have DENIED at least one fork past pids.max={CAP} \
(pids.events max stayed 0 — the limit did not bite)"
);
assert!(
current <= CAP,
"pids.current ({current}) must never exceed the cap ({CAP}) — the cap held"
);
killed.expect("cgroup.kill must succeed on this >=5.14 delegated host");
assert!(
drained.expect("drain poll must read cgroup.procs"),
"the leaf must drain (members exit after SIGKILL) within the bounded poll"
);
removed.expect("the leaf must remove after its members drain");
assert!(!dir.exists(), "the real leaf must be gone after remove");
}