diff --git a/src/sandbox.rs b/src/sandbox.rs index 391cc1f..02cec1d 100644 --- a/src/sandbox.rs +++ b/src/sandbox.rs @@ -43,6 +43,7 @@ pub fn build_command(config: &SandboxConfig) -> Result { add_ro_bind(&mut cmd, path)?; } + cmd.arg("--new-session"); cmd.arg("--die-with-parent"); cmd.arg("--chdir").arg(&config.chdir); diff --git a/tests/integration.rs b/tests/integration.rs index 8eb0292..7e76c7e 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -9,6 +9,28 @@ fn sandbox(extra_args: &[&str]) -> Command { cmd } +fn read_sid_from_stat(stat: &str) -> u32 { + stat.trim() + .split_whitespace() + .nth(5) + .expect("missing field 6 in /proc/self/stat") + .parse() + .expect("failed to parse session ID") +} + +fn read_sid_inside_sandbox(extra_args: &[&str]) -> u32 { + let output = sandbox(extra_args) + .args(["--", "bash", "-c", "cat /proc/self/stat"]) + .output() + .expect("agent-sandbox binary failed to execute"); + read_sid_from_stat(&String::from_utf8_lossy(&output.stdout)) +} + +fn read_sid_current_process() -> u32 { + let stat = fs::read_to_string("/proc/self/stat").expect("failed to read /proc/self/stat"); + read_sid_from_stat(&stat) +} + struct CleanupFile(&'static str); impl Drop for CleanupFile { @@ -303,6 +325,17 @@ fn empty_home_rejected() { ); } +#[test] +fn new_session_isolates_sid() { + let inner_sid = read_sid_inside_sandbox(&[]); + let outer_sid = read_sid_current_process(); + + assert_ne!( + inner_sid, outer_sid, + "sandboxed process should have a different session ID (got {inner_sid} == {outer_sid})" + ); +} + #[test] fn rw_missing_path_errors() { let output = sandbox(&["--rw", "/nonexistent/xyz"])