use super::{LinuxBackend, LANDLOCK_ABI_FLOOR};
use crate::backend::linux::cgroup_run::{cgroup_for_run, pids_cap_for, requires_cgroup_backing};
use crate::contract::backend::Backend;
use crate::contract::budget::{budget_admit, BudgetRequirements, DerivedMinimums, MinGuarantee};
use crate::contract::capability::{
Capability, Enforcement, EvidenceClaim, EvidenceSet, FsAccess, FsConfinement, PathSet,
};
use crate::contract::ids::{BackendId, BoundaryPlanHash};
use crate::contract::plan::{
BoundaryPlan, BoundaryRequirement, EvidenceRequirements, Workload, BOUNDARY_PLAN_SCHEMA_VERSION,
};
use crate::contract::support::RequirementKind;
fn fs_requirement() -> BoundaryRequirement {
BoundaryRequirement::Capability(Capability::Filesystem {
access: FsAccess::Read,
scope: PathSet {
roots: vec!["quarantine/root".to_string()],
},
recursive: true,
confinement: FsConfinement::DeclaredRootsOnly,
})
}
#[test]
fn filesystem_is_enforced_at_or_above_the_abi_floor() {
let backend = LinuxBackend::with_abi_for_test(LANDLOCK_ABI_FLOOR);
let profile = backend.profile(&backend.probe());
let verdict = backend.classify(&fs_requirement(), &profile);
assert_eq!(
verdict.enforcement,
Enforcement::Enforced,
"at/above the ABI floor, Filesystem must be Enforced"
);
assert_eq!(
profile.ceiling_for(RequirementKind::Filesystem).enforcement,
Enforcement::Enforced
);
}
#[test]
fn filesystem_fails_closed_below_the_abi_floor() {
let backend = LinuxBackend::with_abi_for_test(LANDLOCK_ABI_FLOOR - 1);
let profile = backend.profile(&backend.probe());
let verdict = backend.classify(&fs_requirement(), &profile);
assert_eq!(
verdict.enforcement,
Enforcement::Unsupported,
"below the ABI floor, Filesystem MUST fail closed (no unbacked guarantee)"
);
}
#[test]
fn unimplemented_kinds_fail_closed_this_chunk() {
let backend = LinuxBackend::with_abi_for_test(LANDLOCK_ABI_FLOOR);
let profile = backend.profile(&backend.probe());
for kind in [
RequirementKind::NetworkDenyAll,
RequirementKind::ChildSpawnDenyNewTasks,
RequirementKind::ChildSpawnAllowThreads,
RequirementKind::ChildSpawnAllowDescendants,
RequirementKind::TempRoot,
RequirementKind::InheritedFdsOnly,
] {
assert_eq!(
profile.ceiling_for(kind).enforcement,
Enforcement::Unsupported,
"{kind:?} must stay Unsupported until its chunk lands (no inflation)"
);
}
}
#[test]
fn environment_is_enforced_in_the_ceiling() {
let backend = LinuxBackend::with_abi_for_test(LANDLOCK_ABI_FLOOR);
let profile = backend.profile(&backend.probe());
assert_eq!(
profile
.ceiling_for(RequirementKind::Environment)
.enforcement,
Enforcement::Enforced,
"Environment::Exact must be Enforced in the production ceiling"
);
}
#[test]
fn inherited_fds_none_is_enforced_in_the_ceiling() {
let backend = LinuxBackend::with_abi_for_test(LANDLOCK_ABI_FLOOR);
let profile = backend.profile(&backend.probe());
assert_eq!(
profile
.ceiling_for(RequirementKind::InheritedFdsNone)
.enforcement,
Enforcement::Enforced,
"InheritedFds::None must be Enforced in the production ceiling"
);
assert_eq!(
profile
.ceiling_for(RequirementKind::InheritedFdsOnly)
.enforcement,
Enforcement::Unsupported,
"InheritedFds::Only must stay Unsupported (no selective-keep lowering)"
);
}
#[test]
fn kill_is_enforced_with_a_cgroup_base_and_unsupported_without() {
let with = LinuxBackend::with_cgroup_for_test(true);
assert_eq!(
with.profile(&with.probe())
.ceiling_for(RequirementKind::Kill)
.enforcement,
Enforcement::Enforced,
"a cgroup base with atomic cgroup.kill backs Kill Enforced"
);
let without = LinuxBackend::with_abi_for_test(LANDLOCK_ABI_FLOOR);
assert_eq!(
without
.profile(&without.probe())
.ceiling_for(RequirementKind::Kill)
.enforcement,
Enforcement::Unsupported,
"no cgroup base ⇒ Kill Unsupported (no unbacked atomic-kill guarantee)"
);
}
#[test]
fn process_count_budget_is_enforced_only_with_a_cgroup_base() {
let with = LinuxBackend::with_cgroup_for_test(true);
let with_budget = with.probe().budget;
assert_eq!(
with_budget.process_count.enforcement,
Enforcement::Enforced,
"a cgroup base backs process_count Enforced (pids.max)"
);
assert_eq!(
with_budget.cpu_micros.enforcement,
Enforcement::Mediated,
"cpu is NOT capped — Mediated, never an over-claim"
);
assert_eq!(
with_budget.resident_bytes.enforcement,
Enforcement::Mediated
);
let without = LinuxBackend::with_abi_for_test(LANDLOCK_ABI_FLOOR);
assert_eq!(
without.probe().budget.process_count.enforcement,
Enforcement::Mediated,
"no cgroup base ⇒ process_count Mediated (no unbacked pids cap)"
);
}
#[test]
fn resource_usage_evidence_is_advertised_only_when_pids_peak_is_witnessable() {
let resource_usage: EvidenceSet = [EvidenceClaim::ResourceUsage].into_iter().collect();
let with_peak = LinuxBackend::with_cgroup_for_test(true).probe().budget;
assert_eq!(
with_peak.process_count.enforcement,
Enforcement::Enforced,
"the pids.max cap is Enforced regardless of the peak witness"
);
assert_eq!(
with_peak.process_count.evidence, resource_usage,
"pids.peak present ⇒ ResourceUsage evidence advertised"
);
let no_peak = LinuxBackend::with_cgroup_for_test(false).probe().budget;
assert_eq!(
no_peak.process_count.enforcement,
Enforcement::Enforced,
"the cap stays Enforced even without the peak witness (cap != witness)"
);
assert_eq!(
no_peak.process_count.evidence,
EvidenceSet::new(),
"no pids.peak ⇒ NO ResourceUsage evidence (no over-claim of an absent witness)"
);
}
fn cgroup_required_plan(backend: &LinuxBackend) -> BoundaryPlan {
let snap = backend.probe();
let budgets = budget_admit(
&BudgetRequirements::uniform(8, MinGuarantee::Mediated),
&snap.budget,
&DerivedMinimums::default(),
[0u8; 32],
)
.expect("budgets admit against the cgroup-backed profile");
BoundaryPlan {
schema_version: BOUNDARY_PLAN_SCHEMA_VERSION,
plan_id: BoundaryPlanHash([0u8; 32]),
backend: BackendId::new(LinuxBackend::ID),
profile: snap,
admitted: Vec::new(),
workload: Workload::Process {
exe: "/bin/true".to_string(),
args: Vec::new(),
},
budgets,
evidence: EvidenceRequirements::default(),
}
}
#[test]
fn cgroup_for_run_fails_closed_when_a_required_leaf_cannot_be_created() {
let backend = LinuxBackend::with_cgroup_for_test(true);
let plan = cgroup_required_plan(&backend);
assert!(
requires_cgroup_backing(&plan) && pids_cap_for(&plan).is_some(),
"the hand-built plan must genuinely require cgroup backing (Enforced process_count)"
);
let observed = cgroup_for_run(&backend, &plan, Vec::new()).expect_err(
"a required-but-uncreatable cgroup leaf MUST fail closed, never run uncgrouped",
);
assert!(
observed
.iter()
.any(|f| f.kind == "cgroup_required_but_unavailable"),
"the refusal must record WHY it failed closed: {observed:?}"
);
}
#[test]
fn linux_unimplemented_kinds_refuse_at_plan() {
use crate::contract::capability::{Capability, FdPolicy};
use crate::contract::host_control::{CommitDurability, HostControl, PathView};
use crate::contract::plan::{BoundarySpec, PlanError};
use crate::contract::registry::{BackendRegistry, BoundaryPlanner};
use std::sync::Arc;
fn spec_for_kind(kind: RequirementKind) -> BoundarySpec {
let (capabilities, controls) = match kind {
RequirementKind::TempRoot => (
vec![],
vec![HostControl::TempRoot {
visibility: PathView::PrivateToBoundary,
}],
),
RequirementKind::ExposePath => (
vec![],
vec![HostControl::ExposePath {
source: String::new(),
dest: String::new(),
access: FsAccess::Read,
view: PathView::PrivateToBoundary,
}],
),
RequirementKind::CommitArtifact => (
vec![],
vec![HostControl::CommitArtifact {
durability: CommitDurability::Atomic,
}],
),
RequirementKind::DiscardArtifact => (vec![], vec![HostControl::DiscardArtifact]),
RequirementKind::ListOutputs => (vec![], vec![HostControl::ListOutputs]),
RequirementKind::InheritedFdsOnly => (
vec![Capability::InheritedFds {
policy: FdPolicy::Only(vec![3]),
}],
vec![],
),
RequirementKind::Filesystem
| RequirementKind::NetworkDenyAll
| RequirementKind::NetworkAllowList
| RequirementKind::ChildSpawnDenyNewTasks
| RequirementKind::ChildSpawnAllowThreads
| RequirementKind::ChildSpawnAllowDescendants
| RequirementKind::Environment
| RequirementKind::InheritedFdsNone
| RequirementKind::LaunchWorkload
| RequirementKind::CaptureStreams
| RequirementKind::Kill => {
assert!(
std::hint::black_box(false),
"PROPERTY: unexpected kind in linux unimplemented refusal test"
);
(vec![], vec![])
}
};
BoundarySpec {
workload: Workload::Process {
exe: "true".to_string(),
args: Vec::new(),
},
capabilities,
controls,
budgets: BudgetRequirements::deny_all(),
evidence: EvidenceRequirements::default(),
}
}
let backend = LinuxBackend::with_abi_for_test(LANDLOCK_ABI_FLOOR);
let id = backend.id();
let mut registry = BackendRegistry::new();
registry.register(Arc::new(backend) as Arc<dyn Backend>);
let planner = BoundaryPlanner::new(®istry);
for kind in [
RequirementKind::TempRoot,
RequirementKind::ExposePath,
RequirementKind::CommitArtifact,
RequirementKind::DiscardArtifact,
RequirementKind::ListOutputs,
RequirementKind::InheritedFdsOnly,
] {
let result = planner.plan(&spec_for_kind(kind), &id);
assert!(
matches!(result, Err(PlanError::Unsupported { .. })),
"{kind:?} must refuse at plan() on linux (empty ceiling for this chunk), got {result:?}"
);
}
}