#![cfg(all(
feature = "backend-linux",
feature = "dangerous-test-hooks",
target_os = "linux"
))]
use bvisor::{
BackendProfile, Enforcement, LinuxBackend, MechanismDigest, ProfileFacts, QualificationStatus,
RequirementKind, LINUX_QUALIFICATION_LEDGER,
};
#[derive(Debug, PartialEq, Eq)]
enum CouplingViolation {
NoLedgerRow(RequirementKind),
NotProven(RequirementKind, QualificationStatus),
FloorNotSatisfied(RequirementKind),
MechanismDigestMismatch(RequirementKind),
}
impl CouplingViolation {
fn describe(&self) -> String {
match self {
Self::NoLedgerRow(kind) => {
format!("Enforced cell {kind:?} has NO ledger row (uncoupled over-claim)")
}
Self::NotProven(kind, status) => {
format!("Enforced cell {kind:?} ledger row is {status:?}, not Proven")
}
Self::FloorNotSatisfied(kind) => {
format!("Enforced cell {kind:?} Proven row's ProfileFloor is not satisfied")
}
Self::MechanismDigestMismatch(kind) => {
format!("Enforced cell {kind:?} mechanism digest does not match the ledger")
}
}
}
}
fn check_coupling(
enforced: &[RequirementKind],
facts: &ProfileFacts,
mechanism_digest_of: &dyn Fn(RequirementKind) -> MechanismDigest,
) -> Result<(), CouplingViolation> {
for &kind in enforced {
let row = LINUX_QUALIFICATION_LEDGER
.iter()
.find(|r| r.key == kind)
.ok_or(CouplingViolation::NoLedgerRow(kind))?;
if row.status != QualificationStatus::Proven {
return Err(CouplingViolation::NotProven(kind, row.status));
}
if !row.profile_floor.satisfied_by(facts) {
return Err(CouplingViolation::FloorNotSatisfied(kind));
}
if row.mechanism_digest() != mechanism_digest_of(kind) {
return Err(CouplingViolation::MechanismDigestMismatch(kind));
}
}
Ok(())
}
fn live_digest_fn(backend: &LinuxBackend) -> impl Fn(RequirementKind) -> MechanismDigest + '_ {
move |kind| MechanismDigest::of_mechanism(&backend.proof_mechanism(kind, Enforcement::Enforced))
}
fn coupling_for(backend: &LinuxBackend) -> Result<(), CouplingViolation> {
let ceiling: BackendProfile = backend.proof_ceiling();
let enforced = ceiling.enforced_kinds();
check_coupling(&enforced, &backend.proof_facts(), &live_digest_fn(backend))
}
#[test]
fn cgroup_profile_couples_every_enforced_cell_to_a_proven_row() {
let backend = LinuxBackend::with_cgroup_for_proof(true);
let enforced = backend.proof_ceiling().enforced_kinds();
assert!(
enforced.contains(&RequirementKind::Filesystem)
&& enforced.contains(&RequirementKind::Kill)
&& enforced.contains(&RequirementKind::LaunchWorkload)
&& enforced.contains(&RequirementKind::CaptureStreams)
&& enforced.contains(&RequirementKind::NetworkDenyAll)
&& enforced.contains(&RequirementKind::ChildSpawnDenyNewTasks)
&& enforced.contains(&RequirementKind::ChildSpawnAllowDescendants)
&& !enforced.contains(&RequirementKind::ChildSpawnAllowThreads),
"the cgroup profile must advertise the Filesystem/Kill/Launch/Capture/NetworkDenyAll/\
ChildSpawn(DenyNewTasks,AllowDescendants) cells the gate then qualifies, and NOT \
ChildSpawnAllowThreads; got {enforced:?}"
);
let result = coupling_for(&backend);
assert!(
result.is_ok(),
"cgroup profile must couple every Enforced cell to a Proven row: {}",
result.err().map_or_else(String::new, |v| v.describe())
);
}
#[test]
fn at_floor_no_cgroup_profile_couples_and_omits_kill() {
let backend = LinuxBackend::with_abi_for_proof(LinuxBackend::LANDLOCK_ABI_FLOOR);
let enforced = backend.proof_ceiling().enforced_kinds();
assert!(
enforced.contains(&RequirementKind::Filesystem),
"Filesystem is Enforced at the ABI floor: {enforced:?}"
);
assert!(
!enforced.contains(&RequirementKind::Kill),
"Kill must be absent (no cgroup base) so the gate never demands a Kill row: {enforced:?}"
);
let result = coupling_for(&backend);
assert!(
result.is_ok(),
"at-floor profile must couple cleanly: {}",
result.err().map_or_else(String::new, |v| v.describe())
);
}
#[test]
fn below_floor_profile_drops_filesystem_from_the_ceiling() {
let backend = LinuxBackend::with_abi_for_proof(LinuxBackend::LANDLOCK_ABI_FLOOR - 1);
let enforced = backend.proof_ceiling().enforced_kinds();
assert!(
!enforced.contains(&RequirementKind::Filesystem),
"Filesystem must drop out of the ceiling below the ABI floor: {enforced:?}"
);
let result = coupling_for(&backend);
assert!(
result.is_ok(),
"below-floor profile must couple cleanly: {}",
result.err().map_or_else(String::new, |v| v.describe())
);
}
#[test]
fn ledger_mechanism_digest_equals_the_backend_live_digest() {
let backend = LinuxBackend::with_cgroup_for_proof(true);
let row = LINUX_QUALIFICATION_LEDGER
.iter()
.find(|r| r.key == RequirementKind::Filesystem)
.expect("Filesystem ledger row");
let live = MechanismDigest::of_mechanism(
&backend.proof_mechanism(RequirementKind::Filesystem, Enforcement::Enforced),
);
assert_eq!(
row.mechanism_digest(),
live,
"the committed Filesystem mechanism digest must equal the backend's live one"
);
}
#[test]
fn a_swapped_mechanism_is_rejected_by_the_digest_match() {
let backend = LinuxBackend::with_cgroup_for_proof(true);
let enforced = backend.proof_ceiling().enforced_kinds();
let liar = |kind: RequirementKind| {
if kind == RequirementKind::Filesystem {
MechanismDigest::of_mechanism("linux:SWAPPED-UNPROVEN-MECHANISM:Enforced")
} else {
MechanismDigest::of_mechanism(&backend.proof_mechanism(kind, Enforcement::Enforced))
}
};
let result = check_coupling(&enforced, &backend.proof_facts(), &liar);
assert!(
matches!(
result,
Err(CouplingViolation::MechanismDigestMismatch(
RequirementKind::Filesystem
))
),
"a swapped Filesystem mechanism must be rejected as a digest mismatch, got {result:?}"
);
}
#[cfg(gauntlet_red_fixture)]
#[test]
fn coupling_red_fixture_enforced_without_proven_row_must_fail() {
let backend = LinuxBackend::with_cgroup_for_proof(true);
let mut enforced = backend.proof_ceiling().enforced_kinds();
enforced.push(RequirementKind::NetworkAllowList);
let result = check_coupling(&enforced, &backend.proof_facts(), &live_digest_fn(&backend));
assert!(
result.is_ok(),
"RED FIXTURE: a biting coupling gate catches the planted Enforced-without-Proven \
cell, so this assertion must FAIL"
);
}