use std::sync::OnceLock;
use procage_policy::Tier;
use super::sys;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct Probe {
pub tier: Option<Tier>,
pub landlock_abi: u8,
pub errata: u32,
pub userns_errno: Option<i32>,
}
pub(crate) const T1_NAMESPACES: libc::c_int =
libc::CLONE_NEWUSER | libc::CLONE_NEWNS | libc::CLONE_NEWIPC | libc::CLONE_NEWUTS;
pub fn probe() -> &'static Probe {
static PROBE: OnceLock<Probe> = OnceLock::new();
PROBE.get_or_init(|| {
let landlock_abi = sys::landlock_abi()
.ok()
.and_then(|v| u8::try_from(v).ok())
.unwrap_or(0);
let errata = if landlock_abi > 0 {
sys::landlock_errata()
} else {
0
};
let userns_errno = sys::probe_userns(T1_NAMESPACES | libc::CLONE_NEWNET).err();
let tier = if landlock_abi >= Tier::T1.min_landlock_abi() && userns_errno.is_none() {
Some(Tier::T1)
} else if landlock_abi >= Tier::T2.min_landlock_abi() {
Some(Tier::T2)
} else {
None
};
Probe {
tier,
landlock_abi,
errata,
userns_errno,
}
})
}