mirror of
https://github.com/openai/codex.git
synced 2026-04-29 02:41:12 +03:00
Fixes #15283. ## Summary Older system bubblewrap builds reject `--argv0`, which makes our Linux sandbox fail before the helper can re-exec. This PR keeps using system `/usr/bin/bwrap` whenever it exists and only falls back to vendored bwrap when the system binary is missing. That matters on stricter AppArmor hosts, where the distro bwrap package also provides the policy setup needed for user namespaces. For old system bwrap, we avoid `--argv0` instead of switching binaries: - pass the sandbox helper a full-path `argv0`, - keep the existing `current_exe() + --argv0` path when the selected launcher supports it, - otherwise omit `--argv0` and re-exec through the helper's own `argv[0]` path, whose basename still dispatches as `codex-linux-sandbox`. Also updates the launcher/warning tests and docs so they match the new behavior: present-but-old system bwrap uses the compatibility path, and only absent system bwrap falls back to vendored. ### Validation 1. Install Ubuntu 20.04 in a VM 2. Compile codex and run without bubblewrap installed - see a warning about falling back to the vendored bwrap 3. Install bwrap and verify version is 0.4.0 without `argv0` support 4. run codex and use apply_patch tool without errors <img width="802" height="631" alt="Screenshot 2026-03-25 at 11 48 36 PM" src="https://github.com/user-attachments/assets/77248a29-aa38-4d7c-9833-496ec6a458b8" /> <img width="807" height="634" alt="Screenshot 2026-03-25 at 11 47 32 PM" src="https://github.com/user-attachments/assets/5af8b850-a466-489b-95a6-455b76b5050f" /> <img width="812" height="635" alt="Screenshot 2026-03-25 at 11 45 45 PM" src="https://github.com/user-attachments/assets/438074f0-8435-4274-a667-332efdd5cb57" /> <img width="801" height="623" alt="Screenshot 2026-03-25 at 11 43 56 PM" src="https://github.com/user-attachments/assets/0dc8d3f5-e8cf-4218-b4b4-a4f7d9bf02e3" /> --------- Co-authored-by: Michael Bolin <mbolin@openai.com>
160 lines
4.2 KiB
Rust
160 lines
4.2 KiB
Rust
// Aggregates all former standalone integration tests as modules.
|
|
use std::ffi::OsString;
|
|
use std::path::Path;
|
|
|
|
use codex_apply_patch::CODEX_CORE_APPLY_PATCH_ARG1;
|
|
use codex_arg0::Arg0PathEntryGuard;
|
|
use codex_arg0::arg0_dispatch;
|
|
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
|
|
use ctor::ctor;
|
|
use tempfile::TempDir;
|
|
|
|
struct TestCodexAliasesGuard {
|
|
_codex_home: TempDir,
|
|
_arg0: Arg0PathEntryGuard,
|
|
_previous_codex_home: Option<OsString>,
|
|
}
|
|
|
|
const CODEX_HOME_ENV_VAR: &str = "CODEX_HOME";
|
|
|
|
// This code runs before any other tests are run.
|
|
// It allows the test binary to behave like codex and dispatch to apply_patch and codex-linux-sandbox
|
|
// based on the arg0.
|
|
// NOTE: this doesn't work on ARM
|
|
#[ctor]
|
|
pub static CODEX_ALIASES_TEMP_DIR: Option<TestCodexAliasesGuard> = {
|
|
let mut args = std::env::args_os();
|
|
let argv0 = args.next().unwrap_or_default();
|
|
let exe_name = Path::new(&argv0)
|
|
.file_name()
|
|
.and_then(|name| name.to_str())
|
|
.unwrap_or("");
|
|
let argv1 = args.next().unwrap_or_default();
|
|
// Helper re-execs inherit this ctor too, but they may run inside a sandbox
|
|
// where creating another CODEX_HOME tempdir under /tmp is not allowed.
|
|
if exe_name == CODEX_LINUX_SANDBOX_ARG0 || argv1 == CODEX_CORE_APPLY_PATCH_ARG1 {
|
|
return None;
|
|
}
|
|
|
|
#[allow(clippy::unwrap_used)]
|
|
let codex_home = tempfile::Builder::new()
|
|
.prefix("codex-core-tests")
|
|
.tempdir()
|
|
.unwrap();
|
|
let previous_codex_home = std::env::var_os(CODEX_HOME_ENV_VAR);
|
|
// arg0_dispatch() creates helper links under CODEX_HOME/tmp. Point it at a
|
|
// test-owned temp dir so startup never mutates the developer's real ~/.codex.
|
|
//
|
|
// Safety: #[ctor] runs before tests start, so no test threads exist yet.
|
|
unsafe {
|
|
std::env::set_var(CODEX_HOME_ENV_VAR, codex_home.path());
|
|
}
|
|
|
|
#[allow(clippy::unwrap_used)]
|
|
let arg0 = arg0_dispatch().unwrap();
|
|
// Restore the process environment immediately so later tests observe the
|
|
// same CODEX_HOME state they started with.
|
|
match previous_codex_home.as_ref() {
|
|
Some(value) => unsafe {
|
|
std::env::set_var(CODEX_HOME_ENV_VAR, value);
|
|
},
|
|
None => unsafe {
|
|
std::env::remove_var(CODEX_HOME_ENV_VAR);
|
|
},
|
|
}
|
|
|
|
Some(TestCodexAliasesGuard {
|
|
_codex_home: codex_home,
|
|
_arg0: arg0,
|
|
_previous_codex_home: previous_codex_home,
|
|
})
|
|
};
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod abort_tasks;
|
|
mod agent_jobs;
|
|
mod agent_websocket;
|
|
mod apply_patch_cli;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod approvals;
|
|
mod auth_refresh;
|
|
mod cli_stream;
|
|
mod client;
|
|
mod client_websockets;
|
|
mod code_mode;
|
|
mod codex_delegate;
|
|
mod collaboration_instructions;
|
|
mod compact;
|
|
mod compact_remote;
|
|
mod compact_resume_fork;
|
|
mod deprecation_notice;
|
|
mod exec;
|
|
mod exec_policy;
|
|
mod fork_thread;
|
|
mod hierarchical_agents;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod hooks;
|
|
mod image_rollout;
|
|
mod items;
|
|
mod js_repl;
|
|
mod json_result;
|
|
mod live_cli;
|
|
mod live_reload;
|
|
mod memories;
|
|
mod model_info_overrides;
|
|
mod model_overrides;
|
|
mod model_switching;
|
|
mod model_visible_layout;
|
|
mod models_cache_ttl;
|
|
mod models_etag_responses;
|
|
mod otel;
|
|
mod pending_input;
|
|
mod permissions_messages;
|
|
mod personality;
|
|
mod personality_migration;
|
|
mod plugins;
|
|
mod prompt_caching;
|
|
mod quota_exceeded;
|
|
mod realtime_conversation;
|
|
mod remote_env;
|
|
mod remote_models;
|
|
mod request_compression;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod request_permissions;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod request_permissions_tool;
|
|
mod request_user_input;
|
|
mod resume;
|
|
mod resume_warning;
|
|
mod review;
|
|
mod rmcp_client;
|
|
mod rollout_list_find;
|
|
mod safety_check_downgrade;
|
|
mod search_tool;
|
|
mod seatbelt;
|
|
mod shell_command;
|
|
mod shell_serialization;
|
|
mod shell_snapshot;
|
|
mod skill_approval;
|
|
mod skills;
|
|
mod spawn_agent_description;
|
|
mod sqlite_state;
|
|
mod stream_error_allows_next_turn;
|
|
mod stream_no_completed;
|
|
mod subagent_notifications;
|
|
mod text_encoding_fix;
|
|
mod tool_harness;
|
|
mod tool_parallelism;
|
|
mod tool_suggest;
|
|
mod tools;
|
|
mod truncation;
|
|
mod turn_state;
|
|
mod undo;
|
|
mod unified_exec;
|
|
mod unstable_features_warning;
|
|
mod user_notification;
|
|
mod user_shell_cmd;
|
|
mod view_image;
|
|
mod web_search;
|
|
mod websocket_fallback;
|