mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
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:
1 parent
19940967bd
commit
44481a1c45
2 files changed
+39
-34
No files matched your search
@@ -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]
|
||||
|
||||
Reference in new issue
Block a user