use std::process::Command;
use landlock::RulesetError;
pub use landlock::{ABI, AddRulesError, PathFdError, RestrictionStatus};
mod file_permissions;
mod network_permissions;
mod ruleset;
pub use file_permissions::*;
pub use network_permissions::*;
pub use ruleset::{AllowPath, NewInsideRulesetError};
use crate::ruleset::InsideRuleset;
pub struct Inside {
ruleset: InsideRuleset,
}
impl Inside {
pub fn try_new(abi: ABI) -> Result<Self, NewInsideRulesetError> {
Ok(Inside {
ruleset: InsideRuleset::try_new(abi)?,
})
}
pub fn allow_file(
mut self,
path: AllowPath,
permissions: FilePermissions,
) -> Result<Self, AddRulesError> {
self.ruleset = self.ruleset.allow_file(path, permissions)?;
Ok(self)
}
pub fn allow_files<T: AsRef<std::path::Path>>(
mut self,
paths: impl Iterator<Item = T>,
permissions: FilePermissions,
) -> Result<Self, AddRulesError> {
self.ruleset = self.ruleset.allow_files(paths, permissions)?;
Ok(self)
}
pub fn allow_port(
mut self,
port: u16,
permissions: NetworkPermissions,
) -> Result<Self, AddRulesError> {
self.ruleset = self.ruleset.allow_port(port, permissions)?;
Ok(self)
}
pub fn spawn(self, mut command: Command) -> Result<InsideStatus, SpawnInsideError> {
let restriction_status = self.ruleset.restrict().map_err(|e| match e {
RulesetError::RestrictSelf(e) => SpawnInsideError::Restrict(e),
_ => unreachable!(),
})?;
let child_process = command.spawn().map_err(|e| SpawnInsideError::Child(e))?;
Ok(InsideStatus {
child_process,
restriction_status,
})
}
}
#[derive(Debug, thiserror::Error)]
pub enum SpawnInsideError {
#[error(transparent)]
Restrict(landlock::RestrictSelfError),
#[error(transparent)]
Child(std::io::Error),
}
pub struct InsideStatus {
child_process: std::process::Child,
restriction_status: RestrictionStatus,
}
impl InsideStatus {
pub fn child_process(&self) -> &std::process::Child {
&self.child_process
}
pub fn restriction_status(&self) -> &RestrictionStatus {
&self.restriction_status
}
}