use bvisor::{
Backend, BackendRegistry, BoundaryPlanner, BoundarySpec, BudgetRequirements, Capability,
EvidenceRequirements, FsAccess, FsConfinement, HostControl, InertBackend, PathSet, PlanError,
Workload,
};
#[cfg(feature = "dangerous-test-hooks")]
use bvisor::{
BoundaryRecoveryEvent, BoundaryReportEvent, BoundaryRunner, BoundaryStartedEvent, MinGuarantee,
Outcome, StdStreams,
};
use std::sync::Arc;
fn registry() -> BackendRegistry {
let mut registry = BackendRegistry::new();
registry.register(Arc::new(InertBackend::new()));
registry
}
fn inert_id() -> bvisor::BackendId {
InertBackend::new().id()
}
#[cfg(feature = "dangerous-test-hooks")]
fn sim_registry() -> BackendRegistry {
let mut registry = BackendRegistry::new();
registry.register(Arc::new(bvisor::__sim::SimBackend::new(Box::new(
bvisor::__sim::OneShotLiar::new(bvisor::__sim::LieMode::Honest),
))));
registry
}
#[cfg(feature = "dangerous-test-hooks")]
fn sim_id() -> bvisor::BackendId {
bvisor::BackendId::new(bvisor::__sim::SimBackend::ID)
}
fn trivial_workload() -> Workload {
Workload::Process {
exe: "true".to_string(),
args: Vec::new(),
}
}
#[test]
fn plan_fails_closed_on_required_confinement() {
let registry = registry();
let planner = BoundaryPlanner::new(®istry);
let spec = BoundarySpec {
workload: trivial_workload(),
capabilities: vec![Capability::Filesystem {
access: FsAccess::ReadWrite,
scope: PathSet::empty(),
recursive: true,
confinement: FsConfinement::DeclaredRootsOnly,
}],
controls: vec![HostControl::LaunchWorkload],
budgets: BudgetRequirements::deny_all(),
evidence: EvidenceRequirements::default(),
};
let err = planner
.plan(&spec, &inert_id())
.expect_err("inert must refuse real filesystem confinement");
assert!(
matches!(&err, PlanError::Unsupported { backend, .. } if *backend == inert_id()),
"expected Unsupported naming the inert backend, got {err:?}"
);
}
#[cfg(feature = "dangerous-test-hooks")]
#[test]
fn zero_confinement_plans_runs_and_seals_stably() {
let registry = sim_registry();
let planner = BoundaryPlanner::new(®istry);
let runner = BoundaryRunner::new(®istry);
let spec = BoundarySpec {
workload: trivial_workload(),
capabilities: Vec::new(),
controls: vec![
HostControl::LaunchWorkload,
HostControl::CaptureStreams {
streams: StdStreams::capture_out_err(),
},
],
budgets: BudgetRequirements::uniform(64, MinGuarantee::Mediated),
evidence: EvidenceRequirements::default(),
};
let plan = planner
.plan(&spec, &sim_id())
.expect("zero-confinement spec must admit on the honest sim");
assert_eq!(plan.admitted.len(), 2, "both host controls are admitted");
let report = runner.run(&plan).expect("run must seal a report");
assert_eq!(report.body.outcome, Outcome::Completed);
let rehash = report.body.body_hash().expect("body re-hashes");
assert_eq!(rehash, report.body_hash, "seal is reproducible");
let report2 = runner.run(&plan).expect("second run seals");
assert_eq!(
report.body_hash, report2.body_hash,
"identical plans seal identical body hashes"
);
}
#[test]
fn profile_derivation_is_deterministic() {
let backend = InertBackend::new();
let snapshot = backend.probe();
let snapshot_again = backend.probe();
assert_eq!(snapshot, snapshot_again, "probe is deterministic");
let profile = backend.profile(&snapshot);
let profile_again = backend.profile(&snapshot);
assert_eq!(
profile, profile_again,
"profile derivation is deterministic for the same snapshot"
);
}
#[cfg(feature = "dangerous-test-hooks")]
#[test]
fn event_payloads_round_trip() {
let registry = sim_registry();
let planner = BoundaryPlanner::new(®istry);
let runner = BoundaryRunner::new(®istry);
let spec = BoundarySpec {
workload: trivial_workload(),
capabilities: Vec::new(),
controls: vec![HostControl::LaunchWorkload],
budgets: BudgetRequirements::uniform(64, MinGuarantee::Mediated),
evidence: EvidenceRequirements::default(),
};
let plan = planner.plan(&spec, &sim_id()).expect("plan admits");
let report = runner.run(&plan).expect("run seals");
let plan_event = BoundaryStartedEvent { plan: plan.clone() };
let report_event = BoundaryReportEvent {
report: report.clone(),
};
let recovery_event = BoundaryRecoveryEvent {
plan_id: plan.plan_id,
classification: bvisor::RecoveryClassification::Completed,
quarantined: Vec::new(),
};
let plan_bytes = batpak::canonical::to_bytes(&plan_event).expect("encode plan event");
let report_bytes = batpak::canonical::to_bytes(&report_event).expect("encode report event");
let recovery_bytes =
batpak::canonical::to_bytes(&recovery_event).expect("encode recovery event");
let plan_back: BoundaryStartedEvent =
batpak::canonical::from_bytes(&plan_bytes).expect("decode plan event");
let report_back: BoundaryReportEvent =
batpak::canonical::from_bytes(&report_bytes).expect("decode report event");
let recovery_back: BoundaryRecoveryEvent =
batpak::canonical::from_bytes(&recovery_bytes).expect("decode recovery event");
assert_eq!(plan_back, plan_event);
assert_eq!(report_back, report_event);
assert_eq!(recovery_back, recovery_event);
}
#[test]
fn plan_fails_closed_when_required_evidence_uncoverable() {
let registry = registry();
let planner = BoundaryPlanner::new(®istry);
let spec = BoundarySpec {
workload: trivial_workload(),
capabilities: Vec::new(),
controls: vec![HostControl::LaunchWorkload],
budgets: BudgetRequirements::deny_all(),
evidence: EvidenceRequirements {
require_captured_streams: true,
require_exit_status: false,
},
};
let err = planner
.plan(&spec, &inert_id())
.expect_err("inert cannot witness captured streams without CaptureStreams admitted");
assert!(
matches!(&err, PlanError::EvidenceUnsatisfiable { backend, .. } if *backend == inert_id()),
"expected EvidenceUnsatisfiable naming the inert backend, got {err:?}"
);
}
#[cfg(feature = "dangerous-test-hooks")]
#[test]
fn plan_admits_when_required_evidence_is_covered() {
let registry = sim_registry();
let planner = BoundaryPlanner::new(®istry);
let spec = BoundarySpec {
workload: trivial_workload(),
capabilities: Vec::new(),
controls: vec![
HostControl::LaunchWorkload,
HostControl::CaptureStreams {
streams: StdStreams::capture_out_err(),
},
],
budgets: BudgetRequirements::uniform(64, MinGuarantee::Mediated),
evidence: EvidenceRequirements {
require_captured_streams: true,
require_exit_status: true,
},
};
planner
.plan(&spec, &sim_id())
.expect("covered evidence (CapturedStreams + TerminalOutcome) must admit");
}