fix(linux-sandbox): skip nested proxy netns setup

This commit is contained in:
viyatb-oai
2026-02-23 12:42:56 -08:00
parent 7e569f1162
commit 0638857fd2
2 changed files with 93 additions and 0 deletions

View File

@@ -90,6 +90,22 @@ pub fn run_main() -> ! {
}
ensure_inner_stage_mode_is_valid(apply_seccomp_then_exec, use_bwrap_sandbox);
let disable_nested_managed_proxy = should_disable_managed_proxy_for_nested_bwrap(
allow_network_for_proxy,
apply_seccomp_then_exec,
);
if disable_nested_managed_proxy {
eprintln!(
"codex-linux-sandbox: nested Codex bubblewrap sandbox detected; \
skipping inner managed-proxy network namespace setup and relying on outer sandbox network restrictions"
);
}
let allow_network_for_proxy = if disable_nested_managed_proxy {
false
} else {
allow_network_for_proxy
};
// Inner stage: apply seccomp/no_new_privs after bubblewrap has already
// established the filesystem view.
if apply_seccomp_then_exec {
@@ -175,6 +191,63 @@ fn ensure_inner_stage_mode_is_valid(apply_seccomp_then_exec: bool, use_bwrap_san
}
}
fn should_disable_managed_proxy_for_nested_bwrap(
allow_network_for_proxy: bool,
apply_seccomp_then_exec: bool,
) -> bool {
should_disable_managed_proxy_for_nested_bwrap_with_ancestor_bwrap(
allow_network_for_proxy,
apply_seccomp_then_exec,
has_bwrap_ancestor(),
)
}
fn should_disable_managed_proxy_for_nested_bwrap_with_ancestor_bwrap(
allow_network_for_proxy: bool,
apply_seccomp_then_exec: bool,
has_bwrap_ancestor: bool,
) -> bool {
allow_network_for_proxy && !apply_seccomp_then_exec && has_bwrap_ancestor
}
fn has_bwrap_ancestor() -> bool {
const MAX_ANCESTOR_DEPTH: usize = 32;
let mut pid = match parent_pid_of(std::process::id()) {
Some(parent_pid) => parent_pid,
None => return false,
};
for _ in 0..MAX_ANCESTOR_DEPTH {
if pid == 0 {
return false;
}
if process_comm(pid).as_deref() == Some("bwrap") {
return true;
}
pid = match parent_pid_of(pid) {
Some(parent_pid) if parent_pid != pid => parent_pid,
_ => return false,
};
}
false
}
fn process_comm(pid: u32) -> Option<String> {
let path = format!("/proc/{pid}/comm");
let comm = std::fs::read_to_string(path).ok()?;
Some(comm.trim().to_string())
}
fn parent_pid_of(pid: u32) -> Option<u32> {
let path = format!("/proc/{pid}/status");
let status = std::fs::read_to_string(path).ok()?;
status
.lines()
.find_map(|line| line.strip_prefix("PPid:"))
.and_then(|value| value.trim().parse::<u32>().ok())
}
fn run_bwrap_with_proc_fallback(
sandbox_policy_cwd: &Path,
sandbox_policy: &codex_protocol::protocol::SandboxPolicy,

View File

@@ -157,3 +157,23 @@ fn valid_inner_stage_modes_do_not_panic() {
ensure_inner_stage_mode_is_valid(false, true);
ensure_inner_stage_mode_is_valid(true, true);
}
#[test]
fn nested_managed_proxy_fallback_only_applies_to_outer_stage() {
assert_eq!(
should_disable_managed_proxy_for_nested_bwrap_with_ancestor_bwrap(true, false, true),
true
);
assert_eq!(
should_disable_managed_proxy_for_nested_bwrap_with_ancestor_bwrap(true, true, true),
false
);
assert_eq!(
should_disable_managed_proxy_for_nested_bwrap_with_ancestor_bwrap(true, false, false),
false
);
assert_eq!(
should_disable_managed_proxy_for_nested_bwrap_with_ancestor_bwrap(false, false, true),
false
);
}