use crate::checks::LayerResult;
use crate::operation::Operation;
use crate::state::mac::{SeLinuxMode, SeLinuxState};
use crate::state::{Probe, SystemState};
#[must_use]
pub fn check_selinux(state: &SystemState) -> LayerResult {
match &state.mac_state.selinux {
Probe::Unknown => LayerResult::Degraded {
reason: "SELinux state not gathered".into(),
},
Probe::Inaccessible => LayerResult::Degraded {
reason: "SELinux state inaccessible".into(),
},
Probe::Known(sel) => evaluate_selinux_state(sel),
}
}
fn evaluate_selinux_state(sel: &SeLinuxState) -> LayerResult {
match sel.mode {
SeLinuxMode::Disabled => LayerResult::Degraded {
reason: "SELinux disabled on this system".into(),
},
SeLinuxMode::Permissive => build_permissive_result(sel),
SeLinuxMode::Enforcing => build_enforcing_result(sel),
}
}
fn build_permissive_result(sel: &SeLinuxState) -> LayerResult {
let warning = "SELinux is in permissive mode — violations logged but not blocked".to_owned();
if sel.access_allowed {
LayerResult::Pass {
detail: format!(
"SELinux: permissive mode — access allowed (subject: {}, target: {})",
sel.subject_ctx, sel.target_ctx
),
warnings: vec![warning],
}
} else {
LayerResult::Pass {
detail: format!(
"SELinux: permissive mode — would deny (subject: {}, target: {})",
sel.subject_ctx, sel.target_ctx
),
warnings: vec![warning],
}
}
}
fn build_enforcing_result(sel: &SeLinuxState) -> LayerResult {
if sel.access_allowed {
LayerResult::Pass {
detail: format!(
"SELinux: enforcing — access allowed (subject: {}, target: {})",
sel.subject_ctx, sel.target_ctx
),
warnings: vec![],
}
} else {
LayerResult::Fail {
detail: format!(
"SELinux: enforcing — access denied (subject: {}, target: {})",
sel.subject_ctx, sel.target_ctx
),
component_index: None,
}
}
}
#[must_use]
#[allow(clippy::match_same_arms)]
pub fn operation_to_selinux_perm(op: Operation) -> (&'static str, &'static str) {
match op {
Operation::Read | Operation::Stat => ("file", "read"),
Operation::Write | Operation::Create | Operation::Delete => ("file", "write"),
Operation::Execute => ("file", "execute"),
Operation::Chmod | Operation::ChownUid | Operation::ChownGid => ("file", "setattr"),
Operation::SetXattr { .. } => ("file", "setattr"),
}
}
#[cfg(test)]
#[path = "selinux_tests.rs"]
mod tests;