mod landlock;
mod mount;
mod sys;
use std::ffi::OsString;
use std::os::unix::process::CommandExt;
use std::process::{Command, ExitCode};
use anyhow::{anyhow, Result};
use super::{Availability, Backend, Plan};
pub fn availability() -> Vec<(Backend, Availability)> {
vec![
(Backend::Mount, mount::availability()),
(Backend::Landlock, landlock::availability()),
]
}
pub fn enforce_and_exec(plan: &Plan, command: &[OsString]) -> Result<ExitCode> {
match plan.backend {
Backend::Mount => mount::apply(&plan.pinned, &plan.protected)?,
Backend::Landlock => match &plan.carve {
Some(carve) => landlock::apply(carve)?,
None => return Err(anyhow!("internal error: landlock plan was not built")),
},
other => return Err(anyhow!("internal error: {other} cannot enforce on Linux")),
}
Err(exec(command))
}
fn exec(command: &[OsString]) -> anyhow::Error {
let Some((program, arguments)) = command.split_first() else {
return anyhow!("no command given");
};
let error = Command::new(program).args(arguments).exec();
anyhow::Error::new(error).context(format!("failed to run `{}`", program.to_string_lossy()))
}