Spawn bwrap and mirror its exit status instead of exec'ing into it
This commit is contained in:
Generated
+19
@@ -10,6 +10,7 @@ dependencies = [
|
||||
"clap",
|
||||
"glob",
|
||||
"libc",
|
||||
"nix",
|
||||
"seccompiler",
|
||||
"serde",
|
||||
"shlex",
|
||||
@@ -109,6 +110,12 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.7"
|
||||
@@ -255,6 +262,18 @@ version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.31.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
|
||||
@@ -22,6 +22,7 @@ blake3 = "1"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
glob = "0.3"
|
||||
libc = "0.2"
|
||||
nix = { version = "0.31", default-features = false, features = ["signal", "process"] }
|
||||
seccompiler = "0.5"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
shlex = "2.0.1"
|
||||
|
||||
+6
-3
@@ -11,12 +11,15 @@ mod sandbox;
|
||||
mod sandbox_info;
|
||||
mod seccomp;
|
||||
mod session_key;
|
||||
mod signals;
|
||||
|
||||
pub use errors::SandboxError;
|
||||
pub use signals::exit_with_status;
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::process::ExitStatus;
|
||||
|
||||
use crate::sandbox::Bwrap;
|
||||
|
||||
@@ -90,15 +93,15 @@ fn resolve_run_user_from_proc() -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn run(config: SandboxConfig) -> Result<(), SandboxError> {
|
||||
pub fn run(config: SandboxConfig) -> Result<ExitStatus, SandboxError> {
|
||||
preflight::check(&config)?;
|
||||
|
||||
let bwrap = Bwrap::build(&config)?;
|
||||
|
||||
if config.dry_run {
|
||||
println!("{}", bwrap.shell_quoted());
|
||||
return Ok(());
|
||||
return Ok(ExitStatus::default());
|
||||
}
|
||||
|
||||
Err(SandboxError::Io(bwrap.exec()))
|
||||
Ok(bwrap.run()?)
|
||||
}
|
||||
|
||||
+3
-2
@@ -17,8 +17,9 @@ fn main() {
|
||||
|
||||
let config = config::build(args, file_config).unwrap_or_else(|e| exit_err(&e));
|
||||
|
||||
if let Err(e) = agent_sandbox::run(config) {
|
||||
exit_err(&e);
|
||||
match agent_sandbox::run(config) {
|
||||
Ok(status) => agent_sandbox::exit_with_status(status),
|
||||
Err(e) => exit_err(&e),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -1,7 +1,6 @@
|
||||
use std::io;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::process::{Command, ExitStatus};
|
||||
|
||||
use crate::agents;
|
||||
use crate::blacklist;
|
||||
@@ -23,8 +22,8 @@ impl Bwrap {
|
||||
Ok(bwrap)
|
||||
}
|
||||
|
||||
pub fn exec(mut self) -> io::Error {
|
||||
self.command.exec()
|
||||
pub fn run(mut self) -> io::Result<ExitStatus> {
|
||||
self.command.status()
|
||||
}
|
||||
|
||||
pub fn shell_quoted(&self) -> String {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
use std::process::{self, ExitStatus};
|
||||
|
||||
use nix::sys::prctl;
|
||||
use nix::sys::signal::{self, SigHandler, SigSet, Signal};
|
||||
|
||||
pub fn exit_with_status(status: ExitStatus) -> ! {
|
||||
match status.signal() {
|
||||
Some(number) => kill_self_with(number),
|
||||
None => process::exit(status.code().unwrap_or(1)),
|
||||
}
|
||||
}
|
||||
|
||||
fn kill_self_with(number: i32) -> ! {
|
||||
if let Ok(signal) = Signal::try_from(number) {
|
||||
let _ = prctl::set_dumpable(false);
|
||||
let _ = unsafe { signal::signal(signal, SigHandler::SigDfl) };
|
||||
let _ = SigSet::from(signal).thread_unblock();
|
||||
let _ = signal::raise(signal);
|
||||
}
|
||||
|
||||
process::exit(128 + number)
|
||||
}
|
||||
@@ -7,3 +7,4 @@ mod mounts;
|
||||
mod namespaces;
|
||||
mod sandbox_info;
|
||||
mod seccomp;
|
||||
mod signals;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
|
||||
use crate::common::*;
|
||||
|
||||
#[test]
|
||||
fn exit_code_of_entrypoint_is_returned() {
|
||||
let status = Sandbox::new(&[])
|
||||
.args(["--", "sh", "-c", "exit 42"])
|
||||
.status()
|
||||
.expect("agent-sandbox binary failed to execute");
|
||||
|
||||
assert_eq!(status.code(), Some(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signal_death_of_entrypoint_becomes_exit_code() {
|
||||
let status = Sandbox::new(&[])
|
||||
.args(["--", "sh", "-c", "kill -TERM $$"])
|
||||
.status()
|
||||
.expect("agent-sandbox binary failed to execute");
|
||||
|
||||
assert_eq!(status.code(), Some(128 + libc::SIGTERM));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signal_death_of_bwrap_is_mirrored() {
|
||||
let status = Sandbox::new(&["--blacklist"])
|
||||
.args(["--", "sh", "-c", "kill -KILL $PPID; sleep 5"])
|
||||
.status()
|
||||
.expect("agent-sandbox binary failed to execute");
|
||||
|
||||
assert_eq!(status.signal(), Some(libc::SIGKILL));
|
||||
}
|
||||
Reference in New Issue
Block a user