mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Block WSL interop escapes from restricted filesystem sandboxes (#44286)
## Why With network access enabled, WSL interop can launch Windows processes outside the Linux filesystem sandbox, including using `wsl.exe` to reenter the distribution as root. ## What changed - Mask WSL interop sockets in bubblewrap when filesystem write access is restricted, and hide inherited procfs when running without a fresh proc mount. - Deny `AF_VSOCK` sockets and `io_uring` under restricted filesystem policies even when ordinary network access is allowed, closing the VM socket route to host services. - Reject legacy Landlock configurations that combine restricted filesystem access with unrestricted networking when the WSL interop directory exists. ## Testing Add unit coverage for mount masking and legacy policy rejection, plus WSL integration tests for Windows process launch, bind aliases, direct `/init` invocation, root reentry, and `--no-proc` isolation. WSL tests skip when host prerequisites are unavailable. GitOrigin-RevId: 1e8b97ac43675807ee541ca614534d9b1febf410
This commit is contained in:
@@ -203,6 +203,48 @@ fn inserts_unshare_net_when_proxy_only_network_mode_requested() {
|
||||
assert!(argv.contains(&"--unshare-net".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn masks_wsl_interop_with_full_network_and_restricted_filesystem() {
|
||||
let argv = build_bwrap_argv(
|
||||
vec!["/bin/true".to_string()],
|
||||
&read_only_file_system_policy(),
|
||||
Path::new("/"),
|
||||
Path::new("/"),
|
||||
BwrapOptions {
|
||||
network_mode: BwrapNetworkMode::FullAccess,
|
||||
mask_wsl_interop: true,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.expect("build bwrap argv")
|
||||
.args;
|
||||
|
||||
assert!(argv.windows(2).any(|args| args == ["--tmpfs", "/run/WSL"]));
|
||||
assert!(!argv.iter().any(|arg| arg == "--unshare-net"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn masks_inherited_procfs_when_wsl_interop_is_masked_without_fresh_proc() {
|
||||
let argv = build_bwrap_argv(
|
||||
vec!["/bin/true".to_string()],
|
||||
&read_only_file_system_policy(),
|
||||
Path::new("/"),
|
||||
Path::new("/"),
|
||||
BwrapOptions {
|
||||
mount_proc: false,
|
||||
network_mode: BwrapNetworkMode::FullAccess,
|
||||
mask_wsl_interop: true,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.expect("build bwrap argv")
|
||||
.args;
|
||||
|
||||
assert!(argv.windows(2).any(|args| args == ["--tmpfs", "/run/WSL"]));
|
||||
assert!(argv.windows(2).any(|args| args == ["--tmpfs", "/proc"]));
|
||||
assert!(!argv.windows(2).any(|args| args == ["--proc", "/proc"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proxy_only_mode_takes_precedence_over_full_network_policy() {
|
||||
let mode = bwrap_network_mode(
|
||||
@@ -673,13 +715,44 @@ fn legacy_landlock_rejects_split_only_filesystem_policies() {
|
||||
/*use_legacy_landlock*/ true,
|
||||
&policy,
|
||||
NetworkSandboxPolicy::Restricted,
|
||||
/*allow_network_for_proxy*/ false,
|
||||
temp_dir.path(),
|
||||
&temp_dir.path().join("WSL"),
|
||||
);
|
||||
});
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_landlock_rejects_full_network_when_wsl_interop_is_available() {
|
||||
let temp_dir = tempfile::TempDir::new().expect("tempdir");
|
||||
let wsl_interop_dir = temp_dir.path().join("WSL");
|
||||
std::fs::create_dir(&wsl_interop_dir).expect("create interop directory");
|
||||
let policy = read_only_file_system_policy();
|
||||
|
||||
let result = std::panic::catch_unwind(|| {
|
||||
ensure_legacy_landlock_mode_supports_policy(
|
||||
/*use_legacy_landlock*/ true,
|
||||
&policy,
|
||||
NetworkSandboxPolicy::Enabled,
|
||||
/*allow_network_for_proxy*/ false,
|
||||
temp_dir.path(),
|
||||
&wsl_interop_dir,
|
||||
);
|
||||
});
|
||||
assert!(result.is_err());
|
||||
|
||||
ensure_legacy_landlock_mode_supports_policy(
|
||||
/*use_legacy_landlock*/ true,
|
||||
&policy,
|
||||
NetworkSandboxPolicy::Enabled,
|
||||
/*allow_network_for_proxy*/ true,
|
||||
temp_dir.path(),
|
||||
&wsl_interop_dir,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_inner_stage_modes_do_not_panic() {
|
||||
ensure_inner_stage_mode_is_valid(
|
||||
|
||||
Reference in New Issue
Block a user