use crate::contract::capability::Enforcement;
use crate::contract::support::RequirementKind;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[non_exhaustive]
pub enum QualificationStatus {
Proven,
FailClosed,
Incomplete,
Waived,
FaultInjected,
}
impl QualificationStatus {
#[must_use]
pub fn permits_enforced(self) -> bool {
matches!(self, Self::Proven)
}
}
#[must_use]
pub fn enforced_claim_is_qualified(claim: Enforcement, qualification: QualificationStatus) -> bool {
match claim {
Enforcement::Enforced => qualification.permits_enforced(),
Enforcement::Mediated | Enforcement::Unsupported => true,
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct MechanismDigest(pub [u8; 32]);
impl MechanismDigest {
#[must_use]
pub fn of_mechanism(mechanism: &str) -> Self {
Self(batpak::event::hash::compute_hash(mechanism.as_bytes()))
}
#[must_use]
pub fn to_hex(self) -> String {
self.0.iter().map(|b| format!("{b:02x}")).collect()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct ProfileFloor {
pub landlock_abi_min: Option<u8>,
pub requires_cgroup_kill: bool,
pub requires_pids_peak: bool,
pub requires_unprivileged_userns: bool,
pub requires_seccomp_filter: bool,
}
impl ProfileFloor {
#[must_use]
pub const fn structural() -> Self {
Self {
landlock_abi_min: None,
requires_cgroup_kill: false,
requires_pids_peak: false,
requires_unprivileged_userns: false,
requires_seccomp_filter: false,
}
}
#[must_use]
pub const fn unprivileged_userns_netns() -> Self {
Self {
landlock_abi_min: None,
requires_cgroup_kill: false,
requires_pids_peak: false,
requires_unprivileged_userns: true,
requires_seccomp_filter: false,
}
}
#[must_use]
pub const fn seccomp_filter() -> Self {
Self {
landlock_abi_min: None,
requires_cgroup_kill: false,
requires_pids_peak: false,
requires_unprivileged_userns: false,
requires_seccomp_filter: true,
}
}
#[must_use]
pub const fn cgroup_descendant_boundary() -> Self {
Self {
landlock_abi_min: None,
requires_cgroup_kill: true,
requires_pids_peak: false,
requires_unprivileged_userns: false,
requires_seccomp_filter: false,
}
}
#[must_use]
pub fn satisfied_by(&self, facts: &ProfileFacts) -> bool {
if let Some(min) = self.landlock_abi_min {
if facts.landlock_abi < i64::from(min) {
return false;
}
}
if self.requires_cgroup_kill && !facts.has_cgroup_kill {
return false;
}
if self.requires_pids_peak && !facts.has_pids_peak {
return false;
}
if self.requires_unprivileged_userns && !facts.has_unprivileged_userns {
return false;
}
if self.requires_seccomp_filter && !facts.has_seccomp_filter {
return false;
}
true
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ProfileFacts {
pub landlock_abi: i64,
pub has_cgroup_kill: bool,
pub has_pids_peak: bool,
pub has_unprivileged_userns: bool,
pub has_seccomp_filter: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct QualificationRow {
pub backend: &'static str,
pub key: RequirementKind,
pub profile_floor: ProfileFloor,
pub mechanism: &'static str,
pub status: QualificationStatus,
pub proof_receipts: &'static [&'static str],
}
impl QualificationRow {
#[must_use]
pub fn mechanism_digest(&self) -> MechanismDigest {
MechanismDigest::of_mechanism(self.mechanism)
}
}
#[must_use]
pub fn linux_mechanism(primitive: &str, enforcement: Enforcement) -> String {
format!("linux:{primitive}:{enforcement:?}")
}
#[must_use]
pub fn wasm_mechanism(primitive: &str, enforcement: Enforcement) -> String {
format!("wasm:{primitive}:{enforcement:?}")
}
pub const LINUX_QUALIFICATION_LEDGER: &[QualificationRow] = &[
QualificationRow {
backend: "linux",
key: RequirementKind::Filesystem,
profile_floor: ProfileFloor {
landlock_abi_min: Some(1),
requires_cgroup_kill: false,
requires_pids_peak: false,
requires_unprivileged_userns: false,
requires_seccomp_filter: false,
},
mechanism: "linux:landlock:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_linux_fs.rs::g1_landlock_denies_secret_read_outside_declared_root",
],
},
QualificationRow {
backend: "linux",
key: RequirementKind::LaunchWorkload,
profile_floor: ProfileFloor::structural(),
mechanism: "linux:process_spawn:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/launcher_capture_linux.rs::launcher_captures_workload_streams_cleanly_and_deterministically",
"crates/bvisor/tests/launcher_skeleton_linux.rs::missing_primitive_refuses_before_any_child",
],
},
QualificationRow {
backend: "linux",
key: RequirementKind::CaptureStreams,
profile_floor: ProfileFloor::structural(),
mechanism: "linux:pipe_capture:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/launcher_capture_linux.rs::launcher_captures_workload_streams_cleanly_and_deterministically",
],
},
QualificationRow {
backend: "linux",
key: RequirementKind::Kill,
profile_floor: ProfileFloor {
landlock_abi_min: None,
requires_cgroup_kill: true,
requires_pids_peak: false,
requires_unprivileged_userns: false,
requires_seccomp_filter: false,
},
mechanism: "linux:cgroup_kill:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/cgroup_enforcement_linux.rs::pids_max_genuinely_denies_forks_past_the_cap_or_explicit_skip",
],
},
QualificationRow {
backend: "linux",
key: RequirementKind::Environment,
profile_floor: ProfileFloor::structural(),
mechanism: "linux:explicit_env:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/env_exact_linux.rs::child_env_equals_the_admitted_table_with_no_ambient_leak",
"crates/bvisor/tests/env_exact_linux.rs::an_unresolvable_lease_fails_closed_and_the_target_never_runs",
"crates/bvisor/tests/env_exact_linux.rs::a_contract_invalid_policy_is_refused_before_execution",
"crates/bvisor/tests/env_exact_linux.rs::a_secret_lease_resolves_but_the_durable_plan_and_report_carry_only_the_ref",
],
},
QualificationRow {
backend: "linux",
key: RequirementKind::InheritedFdsNone,
profile_floor: ProfileFloor::structural(),
mechanism: "linux:fd_scrub:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/inherited_fds_none_linux.rs::child_inherits_only_the_declared_fds_no_sentinel_leak",
"crates/bvisor/tests/launcher_inherited_fds_linux.rs::undeclared_inherited_fd_is_scrubbed_before_the_workload",
"crates/bvisor/tests/inherited_fds_none_linux.rs::an_unrealized_fd_policy_fails_closed_and_the_target_never_runs",
"crates/bvisor/tests/inherited_fds_none_linux.rs::a_none_policy_spec_runs_through_the_execute_path",
],
},
QualificationRow {
backend: "linux",
key: RequirementKind::InheritedFdsOnly,
profile_floor: ProfileFloor::structural(),
mechanism: "linux:none/unimplemented-this-chunk:Unsupported",
status: QualificationStatus::Incomplete,
proof_receipts: &[],
},
QualificationRow {
backend: "linux",
key: RequirementKind::NetworkDenyAll,
profile_floor: ProfileFloor::unprivileged_userns_netns(),
mechanism: "linux:empty_netns:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/network_deny_all_linux.rs::host_sees_only_loopback_in_the_child_netns_no_external_interface_or_skip",
"crates/bvisor/tests/network_deny_all_linux.rs::workload_cannot_reach_the_network_from_the_empty_netns_or_skip",
"crates/bvisor/tests/network_deny_all_linux.rs::a_deny_all_spec_runs_through_the_execute_path_or_skip",
"crates/bvisor/tests/network_deny_all_linux.rs::network_allow_list_fails_closed_at_admission_the_target_never_runs",
],
},
QualificationRow {
backend: "linux",
key: RequirementKind::NetworkAllowList,
profile_floor: ProfileFloor::structural(),
mechanism: "linux:none/unimplemented-this-chunk:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
QualificationRow {
backend: "linux",
key: RequirementKind::ChildSpawnDenyNewTasks,
profile_floor: ProfileFloor::seccomp_filter(),
mechanism: "linux:seccomp_deny_tasks:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/child_spawn_linux.rs::deny_new_tasks_fork_is_refused_and_host_sees_seccomp_filter_or_skip",
"crates/bvisor/tests/child_spawn_linux.rs::a_deny_new_tasks_spec_runs_through_the_execute_path_or_skip",
"crates/bvisor/tests/child_spawn_linux.rs::allow_threads_fails_closed_at_admission_the_target_never_runs",
],
},
QualificationRow {
backend: "linux",
key: RequirementKind::ChildSpawnAllowThreads,
profile_floor: ProfileFloor::structural(),
mechanism: "linux:none/unimplemented-this-chunk:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
QualificationRow {
backend: "linux",
key: RequirementKind::ChildSpawnAllowDescendants,
profile_floor: ProfileFloor::cgroup_descendant_boundary(),
mechanism: "linux:cgroup_descendant_boundary:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/child_spawn_linux.rs::allow_descendants_is_cgroup_confined_and_cgroup_kill_drains_the_tree_or_skip",
"crates/bvisor/tests/child_spawn_linux.rs::an_allow_descendants_spec_runs_through_the_execute_path_or_skip",
],
},
];
#[must_use]
pub fn linux_ledger_row(key: RequirementKind) -> Option<&'static QualificationRow> {
LINUX_QUALIFICATION_LEDGER.iter().find(|r| r.key == key)
}
pub const WASM_QUALIFICATION_LEDGER: &[QualificationRow] = &[
QualificationRow {
backend: "wasm",
key: RequirementKind::Filesystem,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:wasi_preopen:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::g1_wasi_preopen_denies_secret_read_outside_declared_root",
"crates/bvisor/tests/grid_wasm.rs::g3_wasi_preopen_denies_write_outside_quarantine",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::LaunchWorkload,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:wasi_instantiate:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::wasm_profile_admits_declared_roots_spec",
"crates/bvisor/tests/grid_wasm.rs::g7_wasi_preopen_commit_allows_in_root_output",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::CaptureStreams,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:wasi_stdio:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::wasi_capture_streams_records_guest_output",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::Environment,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:wasi_env:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::wasi_env_exact_is_delivered_to_guest",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::TempRoot,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:wasi_preopen_tmp:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::wasi_temp_root_is_private_and_writable",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::CommitArtifact,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:preopen_commit:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::g7_wasi_preopen_commit_allows_in_root_output",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::DiscardArtifact,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:preopen_commit:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::wasi_temp_root_is_private_and_writable",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::ListOutputs,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:preopen_readdir:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::g7_wasi_preopen_commit_allows_in_root_output",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::NetworkDenyAll,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:no_socket_cap:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::wasi_socket_capability_is_absent",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::InheritedFdsNone,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:wasi_stdio:Enforced",
status: QualificationStatus::Proven,
proof_receipts: &[
"crates/bvisor/tests/grid_wasm.rs::wasi_no_inherited_fds_contract_runs_without_raw_fd_authority",
],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::InheritedFdsOnly,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:none/structurally-unsupported:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::ChildSpawnDenyNewTasks,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:none/structurally-unsupported:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::ChildSpawnAllowThreads,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:none/structurally-unsupported:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::ChildSpawnAllowDescendants,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:none/structurally-unsupported:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::Kill,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:none/structurally-unsupported:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::ExposePath,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:none/structurally-unsupported:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
QualificationRow {
backend: "wasm",
key: RequirementKind::NetworkAllowList,
profile_floor: ProfileFloor::structural(),
mechanism: "wasm:none/structurally-unsupported:Unsupported",
status: QualificationStatus::FailClosed,
proof_receipts: &[],
},
];
#[must_use]
pub fn wasm_ledger_row(key: RequirementKind) -> Option<&'static QualificationRow> {
WASM_QUALIFICATION_LEDGER.iter().find(|r| r.key == key)
}
#[cfg(test)]
#[path = "qualification_tests.rs"]
mod tests;