lazaret/crates/lazaret-linux/tests/capability-drop-helper.rs

54 lines
2.2 KiB
Rust

use std::process::ExitCode;
use rustix::thread::{
CapabilitySet, capabilities, capability_is_in_ambient_set, configure_capability_in_ambient_set,
set_capabilities,
};
#[allow(clippy::disallowed_methods, clippy::disallowed_types)]
fn main() -> ExitCode {
if std::env::var_os("LAZARET_CAPABILITY_DROP_ISOLATED").is_none() {
let before = lazaret_linux::capability::inspect(CapabilitySet::NET_ADMIN)
.expect("inspect unprivileged capability state");
if lazaret_linux::capability::irreversibly_drop(CapabilitySet::NET_ADMIN).is_ok()
|| lazaret_linux::capability::inspect(CapabilitySet::NET_ADMIN).ok() != Some(before)
{
return ExitCode::FAILURE;
}
return match std::process::Command::new("unshare")
.args(["--user", "--map-root-user"])
.arg(std::env::current_exe().expect("test executable path"))
.env("LAZARET_CAPABILITY_DROP_ISOLATED", "1")
.status()
{
Ok(status) if status.success() => ExitCode::SUCCESS,
Ok(_) | Err(_) => ExitCode::FAILURE,
};
}
let capability = CapabilitySet::NET_ADMIN;
let retained = CapabilitySet::CHOWN;
let mut sets = capabilities(None).expect("inspect isolated capability sets");
sets.inheritable.insert(retained);
set_capabilities(None, sets).expect("prepare unrelated ambient capability");
configure_capability_in_ambient_set(retained, true)
.expect("raise unrelated ambient capability");
if lazaret_linux::capability::irreversibly_drop(capability).is_err() {
return ExitCode::FAILURE;
}
let Ok(observed) = lazaret_linux::capability::inspect(capability) else {
return ExitCode::FAILURE;
};
if observed.sets.effective.intersects(capability)
|| observed.sets.permitted.intersects(capability)
|| observed.sets.inheritable.intersects(capability)
|| observed.ambient
|| observed.bounding
|| !capability_is_in_ambient_set(retained).unwrap_or(false)
|| configure_capability_in_ambient_set(capability, true).is_ok()
{
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
}
}