use crate::landlock::{
compat::TryCompat, uapi, Access, AddRuleError, AddRulesError, HandleAccessError,
HandleAccessesError, PrivateAccess, Ruleset, TailoredCompatLevel, ABI,
};
crate::landlock::access::bitflags_type! {
pub struct Scope: u64 {
const AbstractUnixSocket = uapi::LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET as u64;
const Signal = uapi::LANDLOCK_SCOPE_SIGNAL as u64;
}
}
impl TailoredCompatLevel for Scope {}
impl Access for Scope {
fn from_all(abi: ABI) -> Self {
match abi {
ABI::Unsupported | ABI::V1 | ABI::V2 | ABI::V3 | ABI::V4 | ABI::V5 => Scope::EMPTY,
ABI::V6 | ABI::V7 | ABI::V8 => Scope::AbstractUnixSocket | Scope::Signal,
}
}
}
impl PrivateAccess for Scope {
fn is_empty(self) -> bool {
Scope::is_empty(&self)
}
fn ruleset_handle_access(
ruleset: &mut Ruleset,
scope: Self,
) -> Result<(), HandleAccessesError> {
ruleset.requested_scoped |= scope;
if let Some(a) = scope
.try_compat(
ruleset.compat.abi(),
ruleset.compat.level,
&mut ruleset.compat.state,
)
.map_err(HandleAccessError::Compat)?
{
ruleset.actual_scoped |= a;
}
Ok(())
}
fn into_add_rules_error(error: AddRuleError<Self>) -> AddRulesError {
AddRulesError::Scope(error)
}
fn into_handle_accesses_error(error: HandleAccessError<Self>) -> HandleAccessesError {
HandleAccessesError::Scope(error)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::landlock::*;
#[test]
fn test_scope_bitflags_1() {
let unix = Scope::AbstractUnixSocket;
let signal = Scope::Signal;
let both = unix | signal;
assert!(both.contains(unix));
assert!(both.contains(signal));
assert_ne!(unix, signal);
}
#[test]
fn test_scope_bitflags_2() {
assert!(!Scope::EMPTY.contains(Scope::AbstractUnixSocket));
assert!(!Scope::EMPTY.contains(Scope::Signal));
}
#[test]
fn test_scope_from_all_1() {
assert_eq!(Scope::from_all(ABI::Unsupported), Scope::EMPTY);
}
#[test]
fn test_scope_from_all_2() {
assert_eq!(Scope::from_all(ABI::V1), Scope::EMPTY);
}
#[test]
fn test_scope_from_all_3() {
assert_eq!(Scope::from_all(ABI::V2), Scope::EMPTY);
}
#[test]
fn test_scope_from_all_4() {
assert_eq!(Scope::from_all(ABI::V3), Scope::EMPTY);
}
#[test]
fn test_scope_from_all_5() {
assert_eq!(Scope::from_all(ABI::V4), Scope::EMPTY);
}
#[test]
fn test_scope_from_all_6() {
assert_eq!(Scope::from_all(ABI::V5), Scope::EMPTY);
}
#[test]
fn test_scope_from_all_7() {
let expected = Scope::AbstractUnixSocket | Scope::Signal;
assert_eq!(Scope::from_all(ABI::V6), expected);
}
#[test]
fn test_scope_from_all_8() {
let expected = Scope::AbstractUnixSocket | Scope::Signal;
assert_eq!(Scope::from_all(ABI::V7), expected);
}
#[test]
fn test_is_empty_1() {
assert!(PrivateAccess::is_empty(Scope::EMPTY));
}
#[test]
fn test_is_empty_2() {
assert!(!PrivateAccess::is_empty(Scope::Signal));
}
#[test]
fn test_is_empty_3() {
assert!(!PrivateAccess::is_empty(
Scope::AbstractUnixSocket | Scope::Signal
));
}
#[test]
fn test_into_add_rules_error_1() {
let err = AddRuleError::UnhandledAccess {
access: Scope::Signal,
incompatible: Scope::Signal,
};
assert!(matches!(
Scope::into_add_rules_error(err),
AddRulesError::Scope(AddRuleError::UnhandledAccess { .. })
));
}
#[test]
fn test_into_handle_accesses_error_1() {
let err = HandleAccessError::Compat(CompatError::Access(AccessError::Empty));
assert!(matches!(
Scope::into_handle_accesses_error(err),
HandleAccessesError::Scope(HandleAccessError::Compat(CompatError::Access(
AccessError::Empty
)))
));
}
#[test]
fn test_ruleset_handle_access_1() {
let scope = Scope::AbstractUnixSocket | Scope::Signal;
let ruleset = Ruleset::from(ABI::V6).handle_access(scope).unwrap();
assert_eq!(ruleset.requested_scoped, scope);
assert_eq!(ruleset.actual_scoped, scope);
}
#[test]
fn test_ruleset_handle_access_2() {
let scope = Scope::AbstractUnixSocket | Scope::Signal;
let ruleset = Ruleset::from(ABI::V5).handle_access(scope).unwrap();
assert_eq!(ruleset.requested_scoped, scope);
assert_eq!(ruleset.actual_scoped, Scope::EMPTY);
}
}