Files
codex/codex-rs/linux-sandbox/src/bazel_bwrap.rs
T
iceweasel-oai d9960e12bb Add a bubblewrap backend for sandbox integrity checks (#51840)
## What changed

Add Linux dependency discovery and policy preparation to `exec-server`'s sandbox integrity module. Inventory bundled and system `bwrap` candidates and the deny-glob scanner using the launcher's location and the command's `PATH` and working directory.

Resolve `:tmpdir` and tilde-prefixed deny globs using the command's `TMPDIR` and `HOME`, with account home-directory fallback. Reuse Linux sandbox helpers to expand deny globs in the command's explicit environment.

## Testing

Add Linux tests covering symlinked launchers, relative and empty `PATH` entries, and empty, relative, and tilde-prefixed `TMPDIR` values alongside home-relative deny globs.

GitOrigin-RevId: fe404fa4be77ece677b22d52d77a7234dbf0cffe
2026-10-07 21:50:48 +00:00

75 lines
2.2 KiB
Rust

use std::ffi::OsString;
#[cfg(debug_assertions)]
use std::fs::File;
#[cfg(debug_assertions)]
use std::io::BufRead;
use std::path::Path;
use std::path::PathBuf;
#[cfg(debug_assertions)]
const BAZEL_BWRAP_ENV_VAR: &str = "CARGO_BIN_EXE_bwrap";
#[cfg(debug_assertions)]
pub(crate) fn candidate(cwd: &Path, env: impl Fn(&str) -> Option<OsString>) -> Option<PathBuf> {
if option_env!("BAZEL_PACKAGE").is_none() || !runfiles_env_present(&env) {
return None;
}
let raw = PathBuf::from(env(BAZEL_BWRAP_ENV_VAR)?);
if raw.is_absolute() {
return Some(raw);
}
resolve_runfile(raw.to_str()?, cwd, &env)
}
#[cfg(not(debug_assertions))]
pub(crate) fn candidate(_cwd: &Path, _env: impl Fn(&str) -> Option<OsString>) -> Option<PathBuf> {
None
}
#[cfg(debug_assertions)]
fn runfiles_env_present(env: &impl Fn(&str) -> Option<OsString>) -> bool {
env("RUNFILES_DIR").is_some()
|| env("TEST_SRCDIR").is_some()
|| env("RUNFILES_MANIFEST_FILE").is_some()
}
#[cfg(debug_assertions)]
fn resolve_runfile(
logical_path: &str,
cwd: &Path,
env: &impl Fn(&str) -> Option<OsString>,
) -> Option<PathBuf> {
let mut logical_paths = vec![logical_path.to_string()];
if let Some(workspace) = env("TEST_WORKSPACE").and_then(|value| value.into_string().ok())
&& !workspace.is_empty()
{
logical_paths.push(format!("{workspace}/{logical_path}"));
}
for root_env in ["RUNFILES_DIR", "TEST_SRCDIR"] {
let Some(root) = env(root_env) else {
continue;
};
let root = cwd.join(root);
for logical_path in &logical_paths {
let candidate = root.join(logical_path);
if candidate.exists() {
return Some(candidate);
}
}
}
let manifest = cwd.join(env("RUNFILES_MANIFEST_FILE")?);
let file = File::open(manifest).ok()?;
for line in std::io::BufReader::new(file).lines().map_while(Result::ok) {
let Some((key, value)) = line.split_once(' ') else {
continue;
};
if logical_paths.iter().any(|logical_path| logical_path == key) {
return Some(cwd.join(value));
}
}
None
}