Initial commit
This commit is contained in:
132
src/sandbox.rs
Normal file
132
src/sandbox.rs
Normal file
@@ -0,0 +1,132 @@
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use crate::agents;
|
||||
use crate::blacklist;
|
||||
use crate::{SandboxConfig, SandboxError, SandboxMode};
|
||||
|
||||
pub fn build_command(config: &SandboxConfig) -> Result<Command, SandboxError> {
|
||||
let mut cmd = Command::new("bwrap");
|
||||
let hardened = config.hardened || matches!(config.mode, SandboxMode::Whitelist);
|
||||
|
||||
if hardened {
|
||||
cmd.args(["--unshare-ipc", "--unshare-pid", "--unshare-uts"]);
|
||||
cmd.args(["--hostname", "sandbox"]);
|
||||
}
|
||||
if config.no_net {
|
||||
cmd.arg("--unshare-net");
|
||||
}
|
||||
|
||||
match config.mode {
|
||||
SandboxMode::Blacklist => add_blacklist_mode(&mut cmd)?,
|
||||
SandboxMode::Whitelist => add_whitelist_mode(&mut cmd)?,
|
||||
}
|
||||
|
||||
if hardened {
|
||||
cmd.args(["--tmpfs", "/tmp"]);
|
||||
cmd.args(["--dev", "/dev"]);
|
||||
cmd.args(["--tmpfs", "/run"]);
|
||||
cmd.args(["--proc", "/proc"]);
|
||||
}
|
||||
|
||||
for path in agents::agent_rw_paths() {
|
||||
cmd.arg("--bind").arg(&path).arg(&path);
|
||||
}
|
||||
|
||||
add_rw_bind(&mut cmd, &config.chdir)?;
|
||||
for path in &config.extra_rw {
|
||||
add_rw_bind(&mut cmd, path)?;
|
||||
}
|
||||
for path in &config.extra_ro {
|
||||
add_ro_bind(&mut cmd, path)?;
|
||||
}
|
||||
|
||||
cmd.arg("--die-with-parent");
|
||||
cmd.arg("--chdir").arg(&config.chdir);
|
||||
|
||||
cmd.arg("--")
|
||||
.arg(&config.command)
|
||||
.args(&config.command_args);
|
||||
|
||||
Ok(cmd)
|
||||
}
|
||||
|
||||
fn add_blacklist_mode(cmd: &mut Command) -> Result<(), SandboxError> {
|
||||
let ctx = blacklist::resolve_path_context()?;
|
||||
cmd.args(["--ro-bind", "/", "/"]);
|
||||
|
||||
let overlays = blacklist::resolve_overlays(&ctx)?;
|
||||
for dir in &overlays.tmpfs_dirs {
|
||||
cmd.arg("--tmpfs").arg(dir);
|
||||
}
|
||||
for file in &overlays.null_bind_files {
|
||||
cmd.arg("--ro-bind").arg("/dev/null").arg(file);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_whitelist_mode(cmd: &mut Command) -> Result<(), SandboxError> {
|
||||
let home = std::env::var("HOME").map_err(|_| SandboxError::HomeNotSet)?;
|
||||
|
||||
cmd.args(["--ro-bind", "/usr", "/usr"]);
|
||||
for path in ["/lib", "/lib64", "/lib32", "/bin", "/sbin"] {
|
||||
cmd.args(["--ro-bind-try", path, path]);
|
||||
}
|
||||
|
||||
for path in [
|
||||
"/etc/ld.so.cache",
|
||||
"/etc/ld.so.conf",
|
||||
"/etc/ld.so.conf.d",
|
||||
"/etc/alternatives",
|
||||
] {
|
||||
cmd.args(["--ro-bind-try", path, path]);
|
||||
}
|
||||
|
||||
cmd.args(["--ro-bind", "/etc/ssl", "/etc/ssl"]);
|
||||
cmd.args([
|
||||
"--ro-bind-try",
|
||||
"/etc/ca-certificates",
|
||||
"/etc/ca-certificates",
|
||||
]);
|
||||
cmd.args(["--ro-bind", "/etc/resolv.conf", "/etc/resolv.conf"]);
|
||||
cmd.args(["--ro-bind", "/etc/nsswitch.conf", "/etc/nsswitch.conf"]);
|
||||
cmd.args(["--ro-bind", "/etc/passwd", "/etc/passwd"]);
|
||||
cmd.args(["--ro-bind", "/etc/group", "/etc/group"]);
|
||||
|
||||
for path in [
|
||||
"/etc/hosts",
|
||||
"/etc/gai.conf",
|
||||
"/etc/services",
|
||||
"/etc/protocols",
|
||||
] {
|
||||
cmd.args(["--ro-bind-try", path, path]);
|
||||
}
|
||||
|
||||
for path in ["/etc/hostname", "/etc/localtime", "/etc/machine-id"] {
|
||||
cmd.args(["--ro-bind-try", path, path]);
|
||||
}
|
||||
|
||||
let local_bin = format!("{home}/.local/bin");
|
||||
cmd.arg("--ro-bind-try").arg(&local_bin).arg(&local_bin);
|
||||
|
||||
let cache_dir = format!("{home}/.cache");
|
||||
cmd.arg("--tmpfs").arg(&cache_dir);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_rw_bind(cmd: &mut Command, path: &Path) -> Result<(), SandboxError> {
|
||||
if !path.exists() {
|
||||
return Err(SandboxError::RwPathMissing(path.to_path_buf()));
|
||||
}
|
||||
cmd.arg("--bind").arg(path).arg(path);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_ro_bind(cmd: &mut Command, path: &Path) -> Result<(), SandboxError> {
|
||||
if !path.exists() {
|
||||
return Err(SandboxError::RoPathMissing(path.to_path_buf()));
|
||||
}
|
||||
cmd.arg("--ro-bind").arg(path).arg(path);
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user