use crate::LandlockPosture;
#[cfg(all(target_os = "linux", feature = "landlock"))]
pub(crate) fn apply() -> LandlockPosture {
use landlock::{ABI, Access, AccessFs, AccessNet, Ruleset, RulesetAttr, RulesetStatus, Scope};
let kernel_abi = probe_kernel_abi();
if kernel_abi == 0 {
return LandlockPosture::Unsupported {
reason: "kernel does not support landlock",
};
}
let ruleset = Ruleset::default()
.handle_access(AccessFs::from_all(ABI::V6))
.and_then(|r| r.handle_access(AccessNet::BindTcp | AccessNet::ConnectTcp))
.and_then(|r| r.scope(Scope::AbstractUnixSocket | Scope::Signal));
let ruleset = match ruleset {
Ok(r) => r,
Err(_) => {
return LandlockPosture::Unsupported {
reason: "handle_access failed",
};
}
};
let created = match ruleset.create() {
Ok(c) => c,
Err(_) => {
return LandlockPosture::Unsupported {
reason: "ruleset create failed",
};
}
};
let status = match created.restrict_self() {
Ok(s) => s,
Err(_) => {
return LandlockPosture::Unsupported {
reason: "restrict_self failed",
};
}
};
match status.ruleset {
RulesetStatus::FullyEnforced | RulesetStatus::PartiallyEnforced => {
LandlockPosture::Enforced { abi: kernel_abi }
}
RulesetStatus::NotEnforced => LandlockPosture::Unsupported {
reason: "kernel does not support landlock",
},
}
}
#[cfg(all(target_os = "linux", feature = "landlock"))]
fn probe_kernel_abi() -> u32 {
const VERSION_FLAG: u32 = 1;
let v = unsafe {
libc::syscall(
libc::SYS_landlock_create_ruleset,
std::ptr::null::<u8>(),
0_usize,
VERSION_FLAG,
)
};
if v < 0 { 0 } else { v as u32 }
}
#[cfg(not(all(target_os = "linux", feature = "landlock")))]
pub(crate) fn apply() -> LandlockPosture {
LandlockPosture::Disabled
}