Add startup-only PID namespace inheritance to exec-server (#47989)

## Why

When a container denies fresh `/proc` mounts, the existing sandbox fallback retains the caller's `/proc` while creating a new PID namespace. Process IDs inside the sandbox can then differ from those exposed by `/proc`, breaking process lookups.

## What changed

- Add `codex exec-server --linux-sandbox-pid-namespace=inherit` to reuse the caller's PID namespace and `/proc` for both process and filesystem helpers. Repository config and command environment variables cannot enable it.
- Keep `isolate` as the default, preserving the existing mount fallback and compatibility with older helpers. Inheritance requires an updated helper and omits `--unshare-pid` and `--as-pid-1`.
- Preserve other sandbox restrictions. With `:minimal`, bind the inherited `/proc` read-only with its container masks and apply explicit filesystem denials afterward.

Inheritance is intended for dedicated environments: it allows sandboxed commands to signal other same-UID processes, including the executor.

## Testing

Add unit and integration coverage for namespace flags, denied proc mounts, consistent process IDs, retained sandbox restrictions, and startup-only selection across process and filesystem helpers.

GitOrigin-RevId: dd13f2b9286d7edcf366b3a42a455f4d78daaf27
This commit is contained in:
open-matt
2026-09-25 03:12:10 +00:00
committed by copyberry
parent 0f0efab8d3
commit aa380897f6
18 changed files with 494 additions and 31 deletions
+7 -1
View File
@@ -43,6 +43,11 @@ pub(super) struct ExecServerCommand {
)]
pub(super) strict_config: bool,
/// Linux PID namespace: isolate (default) or inherit. Inherit allows signals to
/// other same-UID processes; enable only when provisioning a dedicated environment.
#[arg(long, value_name = "MODE", default_value = "isolate", global = true)]
linux_sandbox_pid_namespace: codex_sandboxing::LinuxSandboxPidNamespace,
/// Maximum number of requests to process concurrently on each connection.
#[arg(
long = "concurrent-requests",
@@ -162,7 +167,8 @@ impl ExecServerCommand {
let runtime_paths = ExecServerRuntimePaths::new(
codex_self_exe,
arg0_paths.codex_linux_sandbox_exe.clone(),
)?;
)?
.with_linux_sandbox_pid_namespace(self.linux_sandbox_pid_namespace);
if let Some(base_url) = self.remote.take() {
let environment_id = self.environment_id.take().ok_or_else(|| {
anyhow::anyhow!("--environment-id is required when --remote is set")