runtime: use install context for bundled bwrap

## Summary

The Linux sandbox should find bundled `bwrap` through the same package-layout abstraction as the rest of the runtime, instead of maintaining a separate standalone-specific lookup path.

This adds an `InstallContext` helper for bundled resources and updates `codex-linux-sandbox` to ask the current install context for `codex-resources/bwrap` before falling back to the old executable-relative probes. The tests cover npm-style, standalone, and canonical package layouts so `bwrap` lookup follows the package structure introduced earlier in the stack.

## Test plan

- `cargo test -p codex-install-context`
- `cargo test -p codex-linux-sandbox --lib`
- `just fix -p codex-install-context -p codex-linux-sandbox`
- `just bazel-lock-check`
This commit is contained in:
Michael Bolin
2026-05-19 23:19:18 -07:00
parent cfa16fcc2e
commit d29a2d0930
4 changed files with 92 additions and 11 deletions

1
codex-rs/Cargo.lock generated
View File

@@ -3017,6 +3017,7 @@ version = "0.0.0"
dependencies = [
"clap",
"codex-core",
"codex-install-context",
"codex-process-hardening",
"codex-protocol",
"codex-sandboxing",

View File

@@ -142,6 +142,30 @@ impl InstallContext {
default_rg_command()
}
pub fn bundled_resource(&self, file_name: impl AsRef<Path>) -> Option<AbsolutePathBuf> {
if let Some(package_layout) = &self.package_layout
&& let Some(resources_dir) = &package_layout.resources_dir
{
let resource = resources_dir.join(file_name.as_ref());
if resource.exists() {
return Some(resource);
}
}
if let InstallMethod::Standalone {
resources_dir: Some(resources_dir),
..
} = &self.method
{
let resource = resources_dir.join(file_name);
if resource.exists() {
return Some(resource);
}
}
None
}
}
impl CodexPackageLayout {
@@ -253,6 +277,7 @@ mod tests {
let exe_path = release_dir.join(if cfg!(windows) { "codex.exe" } else { "codex" });
fs::write(&exe_path, "")?;
fs::write(resources_dir.join(default_rg_command()), "")?;
fs::write(resources_dir.join("bwrap"), "")?;
let canonical_release_dir =
AbsolutePathBuf::from_absolute_path(release_dir.canonicalize()?)?;
let canonical_resources_dir =
@@ -270,12 +295,16 @@ mod tests {
InstallContext {
method: InstallMethod::Standalone {
release_dir: canonical_release_dir,
resources_dir: Some(canonical_resources_dir),
resources_dir: Some(canonical_resources_dir.clone()),
platform: standalone_platform(),
},
package_layout: None,
}
);
assert_eq!(
context.bundled_resource("bwrap"),
Some(canonical_resources_dir.join("bwrap"))
);
Ok(())
}
@@ -312,6 +341,7 @@ mod tests {
fs::write(package_dir.path().join(PACKAGE_METADATA_FILENAME), "{}")?;
let exe_path = bin_dir.join(if cfg!(windows) { "codex.exe" } else { "codex" });
fs::write(&exe_path, "")?;
fs::write(resources_dir.join("bwrap"), "")?;
fs::write(path_dir.join(default_rg_command()), "")?;
let canonical_package_dir =
AbsolutePathBuf::from_absolute_path(package_dir.path().canonicalize()?)?;
@@ -322,7 +352,7 @@ mod tests {
let package_layout = CodexPackageLayout {
package_dir: canonical_package_dir,
bin_dir: canonical_bin_dir,
resources_dir: Some(canonical_resources_dir),
resources_dir: Some(canonical_resources_dir.clone()),
path_dir: Some(canonical_path_dir.clone()),
};
@@ -346,6 +376,10 @@ mod tests {
.join(default_rg_command())
.into_path_buf()
);
assert_eq!(
context.bundled_resource("bwrap"),
Some(canonical_resources_dir.join("bwrap"))
);
Ok(())
}
@@ -364,6 +398,7 @@ mod tests {
fs::write(package_dir.join(PACKAGE_METADATA_FILENAME), "{}")?;
let exe_path = bin_dir.join(if cfg!(windows) { "codex.exe" } else { "codex" });
fs::write(&exe_path, "")?;
fs::write(resources_dir.join("bwrap"), "")?;
fs::write(path_dir.join(default_rg_command()), "")?;
let canonical_package_dir =
AbsolutePathBuf::from_absolute_path(package_dir.canonicalize()?)?;
@@ -390,7 +425,7 @@ mod tests {
package_layout: Some(CodexPackageLayout {
package_dir: canonical_package_dir,
bin_dir: canonical_bin_dir,
resources_dir: Some(canonical_resources_dir),
resources_dir: Some(canonical_resources_dir.clone()),
path_dir: Some(canonical_path_dir.clone()),
}),
}
@@ -401,6 +436,10 @@ mod tests {
.join(default_rg_command())
.into_path_buf()
);
assert_eq!(
context.bundled_resource("bwrap"),
Some(canonical_resources_dir.join("bwrap"))
);
Ok(())
}

View File

@@ -18,6 +18,7 @@ workspace = true
[target.'cfg(target_os = "linux")'.dependencies]
clap = { workspace = true, features = ["derive"] }
codex-install-context = { workspace = true }
codex-process-hardening = { workspace = true }
codex-protocol = { workspace = true }
codex-sandboxing = { workspace = true }

View File

@@ -12,6 +12,7 @@ use std::sync::OnceLock;
use crate::bazel_bwrap;
use crate::exec_util::argv_to_cstrings;
use crate::exec_util::make_files_inheritable;
use codex_install_context::InstallContext;
use codex_utils_absolute_path::AbsolutePathBuf;
use sha2::Digest as _;
use sha2::Sha256;
@@ -26,7 +27,9 @@ pub(crate) struct BundledBwrapLauncher {
pub(crate) fn launcher() -> Option<BundledBwrapLauncher> {
let current_exe = std::env::current_exe().ok()?;
find_for_exe(&current_exe).map(|program| BundledBwrapLauncher { program })
find_for_install_context(InstallContext::current())
.or_else(|| find_legacy_for_exe(&current_exe))
.map(|program| BundledBwrapLauncher { program })
}
impl BundledBwrapLauncher {
@@ -66,8 +69,14 @@ impl BundledBwrapLauncher {
}
}
fn find_for_exe(exe: &Path) -> Option<AbsolutePathBuf> {
candidates_for_exe(exe)
fn find_for_install_context(context: &InstallContext) -> Option<AbsolutePathBuf> {
context
.bundled_resource("bwrap")
.filter(|path| is_executable_file(path))
}
fn find_legacy_for_exe(exe: &Path) -> Option<AbsolutePathBuf> {
legacy_candidates_for_exe(exe)
.into_iter()
.find(|candidate| is_executable_file(candidate))
.map(|path| {
@@ -80,7 +89,7 @@ fn find_for_exe(exe: &Path) -> Option<AbsolutePathBuf> {
})
}
fn candidates_for_exe(exe: &Path) -> Vec<PathBuf> {
fn legacy_candidates_for_exe(exe: &Path) -> Vec<PathBuf> {
let Some(exe_dir) = exe.parent() else {
return Vec::new();
};
@@ -180,13 +189,44 @@ fn bytes_to_hex(bytes: &[u8; 32]) -> String {
#[cfg(test)]
mod tests {
use super::*;
use codex_install_context::CodexPackageLayout;
use codex_install_context::InstallContext;
use codex_install_context::InstallMethod;
use pretty_assertions::assert_eq;
use std::fs;
use tempfile::NamedTempFile;
use tempfile::tempdir;
#[test]
fn finds_standalone_bundled_bwrap_next_to_exe_resources() {
fn finds_package_layout_bwrap_from_install_context() {
let temp_dir = tempdir().expect("temp dir");
let package_dir = temp_dir.path();
let bin_dir = package_dir.join("bin");
let resources_dir = package_dir.join("codex-resources");
let expected_bwrap = resources_dir.join("bwrap");
fs::create_dir_all(&bin_dir).expect("create bin dir");
write_executable(&expected_bwrap);
let context = InstallContext {
method: InstallMethod::Other,
package_layout: Some(CodexPackageLayout {
package_dir: AbsolutePathBuf::from_absolute_path(package_dir).expect("absolute"),
bin_dir: AbsolutePathBuf::from_absolute_path(&bin_dir).expect("absolute"),
resources_dir: Some(
AbsolutePathBuf::from_absolute_path(&resources_dir).expect("absolute"),
),
path_dir: None,
}),
};
assert_eq!(
find_for_install_context(&context),
Some(AbsolutePathBuf::from_absolute_path(&expected_bwrap).expect("absolute"))
);
}
#[test]
fn finds_legacy_standalone_bundled_bwrap_next_to_exe_resources() {
let temp_dir = tempdir().expect("temp dir");
let exe = temp_dir.path().join("codex");
let expected_bwrap = temp_dir.path().join("codex-resources").join("bwrap");
@@ -194,7 +234,7 @@ mod tests {
write_executable(&expected_bwrap);
assert_eq!(
find_for_exe(&exe),
find_legacy_for_exe(&exe),
Some(AbsolutePathBuf::from_absolute_path(&expected_bwrap).expect("absolute"))
);
}
@@ -209,7 +249,7 @@ mod tests {
write_executable(&expected_bwrap);
assert_eq!(
find_for_exe(&exe),
find_legacy_for_exe(&exe),
Some(AbsolutePathBuf::from_absolute_path(&expected_bwrap).expect("absolute"))
);
}
@@ -223,7 +263,7 @@ mod tests {
write_executable(&expected_bwrap);
assert_eq!(
find_for_exe(&exe),
find_legacy_for_exe(&exe),
Some(AbsolutePathBuf::from_absolute_path(&expected_bwrap).expect("absolute"))
);
}