mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
fix(linux-sandbox): avoid panic on bwrap build failures (#21127)
## Summary - Propagate Linux bubblewrap argument-construction failures instead of panicking in the helper - Keep mutable-symlink carveouts fail-closed while reporting them as ordinary sandbox build failures - Add regression coverage for a protected `.codex` symlink inside a writable workspace root ## Root cause Linux bubblewrap intentionally rejects read-only carveouts that cross a symlink the sandboxed process can still rewrite. That is the correct security behavior for protected metadata paths such as `.codex`. The bug was one layer higher: `linux_run_main` treated the expected build failure as impossible and panicked while constructing the bubblewrap argv. For issue #20716, that turned a normal fail-closed sandbox outcome into a noisy panic in the transcript. ## User impact Users with a project-local `.codex` symlink inside a writable workspace still get the conservative sandbox decision, but they no longer see a Rust panic for that condition. The helper now exits with the concise sandbox-build error so the normal denial / escalation path can handle it. Fixes #20716
This commit is contained in:
committed by
GitHub
Unverified
parent
3b2ebb368e
commit
8b95d5467e
@@ -25,6 +25,7 @@ use crate::launcher::exec_bwrap;
|
||||
use crate::launcher::preferred_bwrap_supports_argv0;
|
||||
use crate::proxy_routing::activate_proxy_routes_in_netns;
|
||||
use crate::proxy_routing::prepare_host_proxy_route_spec;
|
||||
use codex_protocol::error::Result as CodexResult;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::FileSystemSandboxPolicy;
|
||||
use codex_protocol::protocol::NetworkSandboxPolicy;
|
||||
@@ -333,6 +334,7 @@ fn run_bwrap_with_proc_fallback(
|
||||
file_system_sandbox_policy,
|
||||
network_mode,
|
||||
)
|
||||
.unwrap_or_else(|err| exit_with_bwrap_build_error(err))
|
||||
{
|
||||
// Keep the retry silent so sandbox-internal diagnostics do not leak into the
|
||||
// child process stderr stream.
|
||||
@@ -350,7 +352,8 @@ fn run_bwrap_with_proc_fallback(
|
||||
sandbox_policy_cwd,
|
||||
command_cwd,
|
||||
options,
|
||||
);
|
||||
)
|
||||
.unwrap_or_else(|err| exit_with_bwrap_build_error(err));
|
||||
apply_inner_command_argv0(&mut bwrap_args.args);
|
||||
run_or_exec_bwrap(bwrap_args);
|
||||
}
|
||||
@@ -374,24 +377,28 @@ fn build_bwrap_argv(
|
||||
sandbox_policy_cwd: &Path,
|
||||
command_cwd: &Path,
|
||||
options: BwrapOptions,
|
||||
) -> crate::bwrap::BwrapArgs {
|
||||
) -> CodexResult<crate::bwrap::BwrapArgs> {
|
||||
let bwrap_args = create_bwrap_command_args(
|
||||
inner,
|
||||
file_system_sandbox_policy,
|
||||
sandbox_policy_cwd,
|
||||
command_cwd,
|
||||
options,
|
||||
)
|
||||
.unwrap_or_else(|err| panic!("error building bubblewrap command: {err:?}"));
|
||||
)?;
|
||||
|
||||
let mut argv = vec!["bwrap".to_string()];
|
||||
argv.extend(bwrap_args.args);
|
||||
crate::bwrap::BwrapArgs {
|
||||
Ok(crate::bwrap::BwrapArgs {
|
||||
args: argv,
|
||||
preserved_files: bwrap_args.preserved_files,
|
||||
synthetic_mount_targets: bwrap_args.synthetic_mount_targets,
|
||||
protected_create_targets: bwrap_args.protected_create_targets,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn exit_with_bwrap_build_error(err: codex_protocol::error::CodexErr) -> ! {
|
||||
eprintln!("error building bubblewrap command: {err}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
fn apply_inner_command_argv0(argv: &mut Vec<String>) {
|
||||
@@ -439,15 +446,15 @@ fn preflight_proc_mount_support(
|
||||
command_cwd: &Path,
|
||||
file_system_sandbox_policy: &FileSystemSandboxPolicy,
|
||||
network_mode: BwrapNetworkMode,
|
||||
) -> bool {
|
||||
) -> CodexResult<bool> {
|
||||
let preflight_argv = build_preflight_bwrap_argv(
|
||||
sandbox_policy_cwd,
|
||||
command_cwd,
|
||||
file_system_sandbox_policy,
|
||||
network_mode,
|
||||
);
|
||||
)?;
|
||||
let stderr = run_bwrap_in_child_capture_stderr(preflight_argv);
|
||||
!is_proc_mount_failure(stderr.as_str())
|
||||
Ok(!is_proc_mount_failure(stderr.as_str()))
|
||||
}
|
||||
|
||||
fn build_preflight_bwrap_argv(
|
||||
@@ -455,7 +462,7 @@ fn build_preflight_bwrap_argv(
|
||||
command_cwd: &Path,
|
||||
file_system_sandbox_policy: &FileSystemSandboxPolicy,
|
||||
network_mode: BwrapNetworkMode,
|
||||
) -> crate::bwrap::BwrapArgs {
|
||||
) -> CodexResult<crate::bwrap::BwrapArgs> {
|
||||
let preflight_command = vec![resolve_true_command()];
|
||||
build_bwrap_argv(
|
||||
preflight_command,
|
||||
|
||||
Reference in New Issue
Block a user