Limit the Linux /proc preflight filesystem view (#34409)

## What changed

- Run the bubblewrap `/proc` mount probe with the minimal read-only filesystem policy instead of the command's filesystem policy and working directory.
- Preserve the requested network namespace mode during the probe.
- Add coverage that the probe mounts a temporary root and `/proc` without binding the full filesystem.

GitOrigin-RevId: e3bc4352f510980aeebe81dedf3f9211947982ed
This commit is contained in:
viyatb-oai authored and copyberry committed 2026-07-20 20:50:02 +00:00
1 parent 19940967bd
commit 44481a1c45
2 files changed
+39 -34

No files matched your search

+18 -25
View File
@@ -27,7 +27,11 @@ 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::FileSystemAccessMode;
use codex_protocol::protocol::FileSystemPath;
use codex_protocol::protocol::FileSystemSandboxEntry;
use codex_protocol::protocol::FileSystemSandboxPolicy;
use codex_protocol::protocol::FileSystemSpecialPath;
use codex_protocol::protocol::NetworkSandboxPolicy;
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
@@ -328,13 +332,8 @@ fn run_bwrap_with_proc_fallback(
let command_cwd = command_cwd.unwrap_or(sandbox_policy_cwd);
if mount_proc
&& !preflight_proc_mount_support(
sandbox_policy_cwd,
command_cwd,
file_system_sandbox_policy,
network_mode,
)
.unwrap_or_else(|err| exit_with_bwrap_build_error(err))
&& !preflight_proc_mount_support(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.
@@ -441,34 +440,28 @@ fn current_process_argv0() -> String {
}
}
fn preflight_proc_mount_support(
sandbox_policy_cwd: &Path,
command_cwd: &Path,
file_system_sandbox_policy: &FileSystemSandboxPolicy,
network_mode: BwrapNetworkMode,
) -> CodexResult<bool> {
let preflight_argv = build_preflight_bwrap_argv(
sandbox_policy_cwd,
command_cwd,
file_system_sandbox_policy,
network_mode,
)?;
fn preflight_proc_mount_support(network_mode: BwrapNetworkMode) -> CodexResult<bool> {
let preflight_argv = build_preflight_bwrap_argv(network_mode)?;
let stderr = run_bwrap_in_child_capture_stderr(preflight_argv);
Ok(!is_proc_mount_failure(stderr.as_str()))
}
fn build_preflight_bwrap_argv(
sandbox_policy_cwd: &Path,
command_cwd: &Path,
file_system_sandbox_policy: &FileSystemSandboxPolicy,
network_mode: BwrapNetworkMode,
) -> CodexResult<crate::bwrap::BwrapArgs> {
let file_system_sandbox_policy =
FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry {
path: FileSystemPath::Special {
value: FileSystemSpecialPath::Minimal,
},
access: FileSystemAccessMode::Read,
}]);
let preflight_command = vec![resolve_true_command()];
build_bwrap_argv(
preflight_command,
file_system_sandbox_policy,
sandbox_policy_cwd,
command_cwd,
&file_system_sandbox_policy,
Path::new("/"),
Path::new("/"),
BwrapOptions {
mount_proc: true,
network_mode,
@@ -258,20 +258,32 @@ fn root_write_read_only_carveout_requires_direct_runtime_enforcement() {
}
#[test]
fn managed_proxy_preflight_argv_is_wrapped_for_full_access_policy() {
fn managed_proxy_preflight_argv_unshares_network() {
let mode = bwrap_network_mode(
NetworkSandboxPolicy::Enabled,
/*allow_network_for_proxy*/ true,
);
let argv = build_preflight_bwrap_argv(
Path::new("/"),
Path::new("/"),
&FileSystemSandboxPolicy::unrestricted(),
mode,
)
.expect("build preflight argv")
.args;
let argv = build_preflight_bwrap_argv(mode)
.expect("build preflight argv")
.args;
assert!(argv.iter().any(|arg| arg == "--"));
assert!(argv.iter().any(|arg| arg == "--unshare-net"));
}
#[test]
fn proc_mount_preflight_does_not_bind_the_full_filesystem() {
let argv = build_preflight_bwrap_argv(BwrapNetworkMode::FullAccess)
.expect("build preflight argv")
.args;
assert!(argv.windows(2).any(|window| window == ["--tmpfs", "/"]));
assert!(argv.windows(2).any(|window| window == ["--proc", "/proc"]));
assert!(
!argv
.windows(3)
.any(|window| window == ["--ro-bind", "/", "/"])
);
assert!(!argv.windows(3).any(|window| window == ["--bind", "/", "/"]));
}
#[test]