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",
|
"clap",
|
||||||
"glob",
|
"glob",
|
||||||
"libc",
|
"libc",
|
||||||
|
"nix",
|
||||||
"seccompiler",
|
"seccompiler",
|
||||||
"serde",
|
"serde",
|
||||||
"shlex",
|
"shlex",
|
||||||
@@ -109,6 +110,12 @@ version = "1.0.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg_aliases"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.6.7"
|
version = "4.6.7"
|
||||||
@@ -255,6 +262,18 @@ version = "0.12.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
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]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.21.4"
|
version = "1.21.4"
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ blake3 = "1"
|
|||||||
clap = { version = "4", features = ["derive"] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
nix = { version = "0.31", default-features = false, features = ["signal", "process"] }
|
||||||
seccompiler = "0.5"
|
seccompiler = "0.5"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
shlex = "2.0.1"
|
shlex = "2.0.1"
|
||||||
|
|||||||
+6
-3
@@ -11,12 +11,15 @@ mod sandbox;
|
|||||||
mod sandbox_info;
|
mod sandbox_info;
|
||||||
mod seccomp;
|
mod seccomp;
|
||||||
mod session_key;
|
mod session_key;
|
||||||
|
mod signals;
|
||||||
|
|
||||||
pub use errors::SandboxError;
|
pub use errors::SandboxError;
|
||||||
|
pub use signals::exit_with_status;
|
||||||
|
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::process::ExitStatus;
|
||||||
|
|
||||||
use crate::sandbox::Bwrap;
|
use crate::sandbox::Bwrap;
|
||||||
|
|
||||||
@@ -90,15 +93,15 @@ fn resolve_run_user_from_proc() -> Option<String> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(config: SandboxConfig) -> Result<(), SandboxError> {
|
pub fn run(config: SandboxConfig) -> Result<ExitStatus, SandboxError> {
|
||||||
preflight::check(&config)?;
|
preflight::check(&config)?;
|
||||||
|
|
||||||
let bwrap = Bwrap::build(&config)?;
|
let bwrap = Bwrap::build(&config)?;
|
||||||
|
|
||||||
if config.dry_run {
|
if config.dry_run {
|
||||||
println!("{}", bwrap.shell_quoted());
|
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));
|
let config = config::build(args, file_config).unwrap_or_else(|e| exit_err(&e));
|
||||||
|
|
||||||
if let Err(e) = agent_sandbox::run(config) {
|
match agent_sandbox::run(config) {
|
||||||
exit_err(&e);
|
Ok(status) => agent_sandbox::exit_with_status(status),
|
||||||
|
Err(e) => exit_err(&e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -1,7 +1,6 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::os::unix::process::CommandExt;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::{Command, ExitStatus};
|
||||||
|
|
||||||
use crate::agents;
|
use crate::agents;
|
||||||
use crate::blacklist;
|
use crate::blacklist;
|
||||||
@@ -23,8 +22,8 @@ impl Bwrap {
|
|||||||
Ok(bwrap)
|
Ok(bwrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec(mut self) -> io::Error {
|
pub fn run(mut self) -> io::Result<ExitStatus> {
|
||||||
self.command.exec()
|
self.command.status()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shell_quoted(&self) -> String {
|
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 namespaces;
|
||||||
mod sandbox_info;
|
mod sandbox_info;
|
||||||
mod seccomp;
|
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