use crate::checks::caps::{has_cap, CAP_DAC_OVERRIDE};
use crate::operation::Operation;
use crate::state::{Probe, SystemState};
use super::LayerResult;
#[must_use]
pub fn capability_modify(result: LayerResult, state: &SystemState) -> LayerResult {
match &result {
LayerResult::Pass { .. } | LayerResult::Degraded { .. } => return result,
LayerResult::Fail { .. } => {}
}
match &state.subject.capabilities {
Probe::Known(bitmask) => {
if has_cap(*bitmask, CAP_DAC_OVERRIDE) {
apply_root_override(state)
} else {
result
}
}
Probe::Unknown => {
if state.subject.uid == 0 {
apply_root_override(state)
} else {
result
}
}
Probe::Inaccessible => result,
}
}
fn apply_root_override(state: &SystemState) -> LayerResult {
if state.operation == Operation::Execute {
return apply_root_execute_override(state);
}
let sticky_note = state.operation == Operation::Delete && parent_has_sticky(state);
let detail = if sticky_note {
"DAC bypassed via CAP_DAC_OVERRIDE (sticky bit on parent also bypassed by root)"
} else {
"DAC bypassed via CAP_DAC_OVERRIDE"
};
LayerResult::Pass {
detail: detail.into(),
warnings: vec![],
}
}
fn parent_has_sticky(state: &SystemState) -> bool {
state
.operation
.target_component(state.walk.len())
.and_then(|i| state.walk[i].stat.known())
.is_some_and(|s| s.mode & 0o1000 != 0)
}
fn apply_root_execute_override(state: &SystemState) -> LayerResult {
let target_idx = state.operation.target_component(state.walk.len());
let any_x = target_idx
.and_then(|i| state.walk[i].stat.known())
.is_some_and(|s| s.mode & 0o111 != 0);
if any_x {
LayerResult::Pass {
detail: "DAC bypassed via CAP_DAC_OVERRIDE".into(),
warnings: vec![],
}
} else {
LayerResult::Fail {
detail: "root cannot execute: no execute bit set on any class \
(CAP_DAC_OVERRIDE does not apply)"
.into(),
component_index: target_idx,
}
}
}