mirror of
https://github.com/openai/codex.git
synced 2026-11-12 22:42:36 +00:00
windows-sandbox: feed setup from resolved permissions (#23167)
## Why This is the next step in the Windows sandbox migration away from the legacy `SandboxPolicy` abstraction. #22923 moved write-root and token decisions onto `ResolvedWindowsSandboxPermissions`, but setup and identity still accepted `SandboxPolicy` and converted internally. This PR pushes that conversion outward so the setup path consumes the resolved Windows permission view directly. ## What Changed - Changed `SandboxSetupRequest` to carry `ResolvedWindowsSandboxPermissions` instead of `SandboxPolicy` plus policy cwd. - Updated setup refresh/elevation and identity credential preparation to use resolved permissions for read roots, write roots, network identity, and deny-write payload planning. - Removed the production `allow.rs` legacy wrapper; allow-path computation now takes resolved permissions directly. - Added a permissions-based world-writable audit entry point while keeping the existing legacy wrapper for compatibility. - Updated legacy ACL setup and the core Windows setup bridge to construct resolved permissions at the boundary. - Hardened the Windows sandbox integration test helper staging so Bazel retries can reuse an already-staged helper if a prior sandbox helper process still has the executable open. ## Verification - `cargo test -p codex-windows-sandbox` - `cargo test -p codex-core --test all --no-run` - `just fix -p codex-windows-sandbox` - `just fix -p codex-core` - Attempted `cargo check -p codex-windows-sandbox --target x86_64-pc-windows-gnullvm`, but the local machine is missing `x86_64-w64-mingw32-clang`; Windows CI should cover that target. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23167). * #23715 * #23714 * __->__ #23167
This commit is contained in:
1 parent
80c4a978f8
commit
896ee672cc
11 files changed
+201
-117
No files matched your search
@@ -179,10 +179,13 @@ pub fn run_elevated_setup(
|
|||||||
env_map: &HashMap<String, String>,
|
env_map: &HashMap<String, String>,
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let permissions =
|
||||||
|
codex_windows_sandbox::ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(
|
||||||
|
policy, policy_cwd,
|
||||||
|
);
|
||||||
codex_windows_sandbox::run_elevated_setup(
|
codex_windows_sandbox::run_elevated_setup(
|
||||||
codex_windows_sandbox::SandboxSetupRequest {
|
codex_windows_sandbox::SandboxSetupRequest {
|
||||||
policy,
|
permissions: &permissions,
|
||||||
policy_cwd,
|
|
||||||
command_cwd,
|
command_cwd,
|
||||||
env_map,
|
env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
|
|||||||
@@ -93,7 +93,22 @@ fn stage_windows_sandbox_helpers() -> anyhow::Result<()> {
|
|||||||
for helper_name in ["codex-windows-sandbox-setup", "codex-command-runner"] {
|
for helper_name in ["codex-windows-sandbox-setup", "codex-command-runner"] {
|
||||||
let helper = codex_utils_cargo_bin::cargo_bin(helper_name)?;
|
let helper = codex_utils_cargo_bin::cargo_bin(helper_name)?;
|
||||||
let file_name = Path::new(helper_name).with_extension("exe");
|
let file_name = Path::new(helper_name).with_extension("exe");
|
||||||
std::fs::copy(helper, resources_dir.join(file_name))?;
|
let destination = resources_dir.join(file_name);
|
||||||
|
if let Err(err) = std::fs::copy(&helper, &destination) {
|
||||||
|
// A sandbox helper can briefly remain alive after the sandboxed
|
||||||
|
// command exits. Bazel may retry the test while that process still
|
||||||
|
// has the staged executable open, so keep the already-staged copy.
|
||||||
|
if err.kind() == std::io::ErrorKind::PermissionDenied && destination.exists() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return Err(err).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"stage Windows sandbox helper {} at {}",
|
||||||
|
helper.display(),
|
||||||
|
destination.display()
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::policy::SandboxPolicy;
|
|
||||||
use crate::resolved_permissions::ResolvedWindowsSandboxPermissions;
|
use crate::resolved_permissions::ResolvedWindowsSandboxPermissions;
|
||||||
use dunce::canonicalize;
|
use dunce::canonicalize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -12,17 +11,6 @@ pub struct AllowDenyPaths {
|
|||||||
pub deny: HashSet<PathBuf>,
|
pub deny: HashSet<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compute_allow_paths(
|
|
||||||
policy: &SandboxPolicy,
|
|
||||||
policy_cwd: &Path,
|
|
||||||
command_cwd: &Path,
|
|
||||||
env_map: &HashMap<String, String>,
|
|
||||||
) -> AllowDenyPaths {
|
|
||||||
let permissions =
|
|
||||||
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(policy, policy_cwd);
|
|
||||||
compute_allow_paths_for_permissions(&permissions, command_cwd, env_map)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn compute_allow_paths_for_permissions(
|
pub(crate) fn compute_allow_paths_for_permissions(
|
||||||
permissions: &ResolvedWindowsSandboxPermissions,
|
permissions: &ResolvedWindowsSandboxPermissions,
|
||||||
command_cwd: &Path,
|
command_cwd: &Path,
|
||||||
@@ -61,6 +49,17 @@ mod tests {
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
|
fn compute_allow_paths(
|
||||||
|
policy: &SandboxPolicy,
|
||||||
|
policy_cwd: &Path,
|
||||||
|
command_cwd: &Path,
|
||||||
|
env_map: &HashMap<String, String>,
|
||||||
|
) -> AllowDenyPaths {
|
||||||
|
let permissions =
|
||||||
|
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(policy, policy_cwd);
|
||||||
|
compute_allow_paths_for_permissions(&permissions, command_cwd, env_map)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn includes_additional_writable_roots() {
|
fn includes_additional_writable_roots() {
|
||||||
let tmp = TempDir::new().expect("tempdir");
|
let tmp = TempDir::new().expect("tempdir");
|
||||||
|
|||||||
@@ -224,15 +224,33 @@ pub fn apply_world_writable_scan_and_denies(
|
|||||||
env_map: &std::collections::HashMap<String, String>,
|
env_map: &std::collections::HashMap<String, String>,
|
||||||
sandbox_policy: &SandboxPolicy,
|
sandbox_policy: &SandboxPolicy,
|
||||||
logs_base_dir: Option<&Path>,
|
logs_base_dir: Option<&Path>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let permissions =
|
||||||
|
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(sandbox_policy, cwd);
|
||||||
|
apply_world_writable_scan_and_denies_for_permissions(
|
||||||
|
codex_home,
|
||||||
|
cwd,
|
||||||
|
env_map,
|
||||||
|
&permissions,
|
||||||
|
logs_base_dir,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_world_writable_scan_and_denies_for_permissions(
|
||||||
|
codex_home: &Path,
|
||||||
|
cwd: &Path,
|
||||||
|
env_map: &std::collections::HashMap<String, String>,
|
||||||
|
permissions: &ResolvedWindowsSandboxPermissions,
|
||||||
|
logs_base_dir: Option<&Path>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let flagged = audit_everyone_writable(cwd, env_map, logs_base_dir)?;
|
let flagged = audit_everyone_writable(cwd, env_map, logs_base_dir)?;
|
||||||
if flagged.is_empty() {
|
if flagged.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if let Err(err) = apply_capability_denies_for_world_writable(
|
if let Err(err) = apply_capability_denies_for_world_writable_for_permissions(
|
||||||
codex_home,
|
codex_home,
|
||||||
&flagged,
|
&flagged,
|
||||||
sandbox_policy,
|
permissions,
|
||||||
cwd,
|
cwd,
|
||||||
env_map,
|
env_map,
|
||||||
logs_base_dir,
|
logs_base_dir,
|
||||||
@@ -245,10 +263,10 @@ pub fn apply_world_writable_scan_and_denies(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_capability_denies_for_world_writable(
|
fn apply_capability_denies_for_world_writable_for_permissions(
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
flagged: &[PathBuf],
|
flagged: &[PathBuf],
|
||||||
sandbox_policy: &SandboxPolicy,
|
permissions: &ResolvedWindowsSandboxPermissions,
|
||||||
cwd: &Path,
|
cwd: &Path,
|
||||||
env_map: &std::collections::HashMap<String, String>,
|
env_map: &std::collections::HashMap<String, String>,
|
||||||
logs_base_dir: Option<&Path>,
|
logs_base_dir: Option<&Path>,
|
||||||
@@ -260,18 +278,13 @@ pub fn apply_capability_denies_for_world_writable(
|
|||||||
let cap_path = cap_sid_file(codex_home);
|
let cap_path = cap_sid_file(codex_home);
|
||||||
let caps = load_or_create_cap_sids(codex_home)?;
|
let caps = load_or_create_cap_sids(codex_home)?;
|
||||||
std::fs::write(&cap_path, serde_json::to_string(&caps)?)?;
|
std::fs::write(&cap_path, serde_json::to_string(&caps)?)?;
|
||||||
if matches!(
|
if !permissions.is_enforceable_by_windows_sandbox() {
|
||||||
sandbox_policy,
|
|
||||||
SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. }
|
|
||||||
) {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let permissions =
|
|
||||||
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(sandbox_policy, cwd);
|
|
||||||
let (active_sids, workspace_roots): (Vec<LocalSid>, Vec<PathBuf>) =
|
let (active_sids, workspace_roots): (Vec<LocalSid>, Vec<PathBuf>) =
|
||||||
if permissions.uses_write_capabilities_for_cwd(cwd, env_map) {
|
if permissions.uses_write_capabilities_for_cwd(cwd, env_map) {
|
||||||
let roots = effective_write_roots_for_permissions(
|
let roots = effective_write_roots_for_permissions(
|
||||||
&permissions,
|
permissions,
|
||||||
cwd,
|
cwd,
|
||||||
env_map,
|
env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
|
|||||||
@@ -97,8 +97,7 @@ mod windows_impl {
|
|||||||
let logs_base_dir: Option<&Path> = Some(sandbox_base.as_path());
|
let logs_base_dir: Option<&Path> = Some(sandbox_base.as_path());
|
||||||
log_start(&command, logs_base_dir);
|
log_start(&command, logs_base_dir);
|
||||||
let sandbox_creds = require_logon_sandbox_creds(
|
let sandbox_creds = require_logon_sandbox_creds(
|
||||||
&policy,
|
&permissions,
|
||||||
sandbox_policy_cwd,
|
|
||||||
cwd,
|
cwd,
|
||||||
&env_map,
|
&env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::dpapi;
|
use crate::dpapi;
|
||||||
use crate::logging::debug_log;
|
use crate::logging::debug_log;
|
||||||
use crate::policy::SandboxPolicy;
|
|
||||||
use crate::resolved_permissions::ResolvedWindowsSandboxPermissions;
|
use crate::resolved_permissions::ResolvedWindowsSandboxPermissions;
|
||||||
use crate::setup::SandboxNetworkIdentity;
|
use crate::setup::SandboxNetworkIdentity;
|
||||||
use crate::setup::SandboxUserRecord;
|
use crate::setup::SandboxUserRecord;
|
||||||
@@ -132,8 +131,7 @@ fn select_identity(
|
|||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn require_logon_sandbox_creds(
|
pub fn require_logon_sandbox_creds(
|
||||||
policy: &SandboxPolicy,
|
permissions: &ResolvedWindowsSandboxPermissions,
|
||||||
policy_cwd: &Path,
|
|
||||||
command_cwd: &Path,
|
command_cwd: &Path,
|
||||||
env_map: &HashMap<String, String>,
|
env_map: &HashMap<String, String>,
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
@@ -144,16 +142,14 @@ pub fn require_logon_sandbox_creds(
|
|||||||
deny_write_paths_override: &[PathBuf],
|
deny_write_paths_override: &[PathBuf],
|
||||||
proxy_enforced: bool,
|
proxy_enforced: bool,
|
||||||
) -> Result<SandboxCreds> {
|
) -> Result<SandboxCreds> {
|
||||||
let permissions =
|
|
||||||
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(policy, policy_cwd);
|
|
||||||
let sandbox_dir = crate::setup::sandbox_dir(codex_home);
|
let sandbox_dir = crate::setup::sandbox_dir(codex_home);
|
||||||
let needed_read = read_roots_override
|
let needed_read = read_roots_override
|
||||||
.map(<[PathBuf]>::to_vec)
|
.map(<[PathBuf]>::to_vec)
|
||||||
.unwrap_or_else(|| gather_read_roots(command_cwd, policy, codex_home));
|
.unwrap_or_else(|| gather_read_roots(command_cwd, permissions, env_map, codex_home));
|
||||||
let needed_write = write_roots_override
|
let needed_write = write_roots_override
|
||||||
.map(<[PathBuf]>::to_vec)
|
.map(<[PathBuf]>::to_vec)
|
||||||
.unwrap_or_else(|| gather_write_roots_for_permissions(&permissions, command_cwd, env_map));
|
.unwrap_or_else(|| gather_write_roots_for_permissions(permissions, command_cwd, env_map));
|
||||||
let network_identity = SandboxNetworkIdentity::from_permissions(&permissions, proxy_enforced);
|
let network_identity = SandboxNetworkIdentity::from_permissions(permissions, proxy_enforced);
|
||||||
let desired_offline_proxy_settings = offline_proxy_settings_from_env(env_map, network_identity);
|
let desired_offline_proxy_settings = offline_proxy_settings_from_env(env_map, network_identity);
|
||||||
// NOTE: Do not add CODEX_HOME/.sandbox to `needed_write`; it must remain non-writable by the
|
// NOTE: Do not add CODEX_HOME/.sandbox to `needed_write`; it must remain non-writable by the
|
||||||
// restricted capability token. The setup helper's `lock_sandbox_dir` is responsible for
|
// restricted capability token. The setup helper's `lock_sandbox_dir` is responsible for
|
||||||
@@ -194,8 +190,7 @@ pub fn require_logon_sandbox_creds(
|
|||||||
}
|
}
|
||||||
run_elevated_setup(
|
run_elevated_setup(
|
||||||
crate::setup::SandboxSetupRequest {
|
crate::setup::SandboxSetupRequest {
|
||||||
policy,
|
permissions,
|
||||||
policy_cwd,
|
|
||||||
command_cwd,
|
command_cwd,
|
||||||
env_map,
|
env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
@@ -214,8 +209,7 @@ pub fn require_logon_sandbox_creds(
|
|||||||
// Always refresh ACLs (non-elevated) for current roots via the setup binary.
|
// Always refresh ACLs (non-elevated) for current roots via the setup binary.
|
||||||
run_setup_refresh_with_overrides(
|
run_setup_refresh_with_overrides(
|
||||||
crate::setup::SandboxSetupRequest {
|
crate::setup::SandboxSetupRequest {
|
||||||
policy,
|
permissions,
|
||||||
policy_cwd,
|
|
||||||
command_cwd,
|
command_cwd,
|
||||||
env_map,
|
env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ pub use acl::path_mask_allows;
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub use audit::apply_world_writable_scan_and_denies;
|
pub use audit::apply_world_writable_scan_and_denies;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
pub use audit::apply_world_writable_scan_and_denies_for_permissions;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
pub use cap::load_or_create_cap_sids;
|
pub use cap::load_or_create_cap_sids;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub use cap::workspace_cap_sid_for_cwd;
|
pub use cap::workspace_cap_sid_for_cwd;
|
||||||
@@ -199,6 +201,8 @@ pub use process::read_handle_loop;
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub use process::spawn_process_with_pipes;
|
pub use process::spawn_process_with_pipes;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
pub use resolved_permissions::ResolvedWindowsSandboxPermissions;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
pub use resolved_permissions::WindowsSandboxTokenMode;
|
pub use resolved_permissions::WindowsSandboxTokenMode;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub use resolved_permissions::token_mode_for_permission_profile;
|
pub use resolved_permissions::token_mode_for_permission_profile;
|
||||||
@@ -291,6 +295,7 @@ mod windows_impl {
|
|||||||
use super::logging::log_success;
|
use super::logging::log_success;
|
||||||
use super::policy::SandboxPolicy;
|
use super::policy::SandboxPolicy;
|
||||||
use super::process::create_process_as_user;
|
use super::process::create_process_as_user;
|
||||||
|
use super::resolved_permissions::ResolvedWindowsSandboxPermissions;
|
||||||
use super::sandbox_utils::ensure_codex_home_exists;
|
use super::sandbox_utils::ensure_codex_home_exists;
|
||||||
use super::spawn_prep::LegacyAclSids;
|
use super::spawn_prep::LegacyAclSids;
|
||||||
use super::spawn_prep::SpawnPrepOptions;
|
use super::spawn_prep::SpawnPrepOptions;
|
||||||
@@ -412,6 +417,7 @@ mod windows_impl {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let policy = common.policy;
|
let policy = common.policy;
|
||||||
|
let permissions = common.permissions;
|
||||||
let current_dir = common.current_dir;
|
let current_dir = common.current_dir;
|
||||||
let logs_base_dir = common.logs_base_dir.as_deref();
|
let logs_base_dir = common.logs_base_dir.as_deref();
|
||||||
let uses_write_capabilities = common.uses_write_capabilities;
|
let uses_write_capabilities = common.uses_write_capabilities;
|
||||||
@@ -435,8 +441,7 @@ mod windows_impl {
|
|||||||
let security = prepare_legacy_session_security(&policy, codex_home, cwd, capability_roots)?;
|
let security = prepare_legacy_session_security(&policy, codex_home, cwd, capability_roots)?;
|
||||||
allow_null_device_for_workspace_write(uses_write_capabilities);
|
allow_null_device_for_workspace_write(uses_write_capabilities);
|
||||||
apply_legacy_session_acl_rules(
|
apply_legacy_session_acl_rules(
|
||||||
&policy,
|
&permissions,
|
||||||
sandbox_policy_cwd,
|
|
||||||
codex_home,
|
codex_home,
|
||||||
¤t_dir,
|
¤t_dir,
|
||||||
&env_map,
|
&env_map,
|
||||||
@@ -602,8 +607,10 @@ mod windows_impl {
|
|||||||
);
|
);
|
||||||
let write_root_sids = root_capability_sids(codex_home, cwd, capability_roots)?;
|
let write_root_sids = root_capability_sids(codex_home, cwd, capability_roots)?;
|
||||||
apply_legacy_session_acl_rules(
|
apply_legacy_session_acl_rules(
|
||||||
sandbox_policy,
|
&ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(
|
||||||
sandbox_policy_cwd,
|
sandbox_policy,
|
||||||
|
sandbox_policy_cwd,
|
||||||
|
),
|
||||||
codex_home,
|
codex_home,
|
||||||
¤t_dir,
|
¤t_dir,
|
||||||
env_map,
|
env_map,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use std::path::PathBuf;
|
|||||||
/// Windows-specific path conventions, not the user/config-facing
|
/// Windows-specific path conventions, not the user/config-facing
|
||||||
/// `PermissionProfile` enum itself.
|
/// `PermissionProfile` enum itself.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub(crate) struct ResolvedWindowsSandboxPermissions {
|
pub struct ResolvedWindowsSandboxPermissions {
|
||||||
file_system: FileSystemSandboxPolicy,
|
file_system: FileSystemSandboxPolicy,
|
||||||
network: NetworkSandboxPolicy,
|
network: NetworkSandboxPolicy,
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ pub fn token_mode_for_permission_profile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ResolvedWindowsSandboxPermissions {
|
impl ResolvedWindowsSandboxPermissions {
|
||||||
pub(crate) fn from_legacy_policy_for_cwd(policy: &SandboxPolicy, cwd: &Path) -> Self {
|
pub fn from_legacy_policy_for_cwd(policy: &SandboxPolicy, cwd: &Path) -> Self {
|
||||||
Self {
|
Self {
|
||||||
file_system: FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(policy, cwd)
|
file_system: FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(policy, cwd)
|
||||||
.materialize_project_roots_with_cwd(cwd),
|
.materialize_project_roots_with_cwd(cwd),
|
||||||
@@ -64,9 +64,7 @@ impl ResolvedWindowsSandboxPermissions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn try_from_permission_profile(
|
pub fn try_from_permission_profile(permission_profile: &PermissionProfile) -> Result<Self> {
|
||||||
permission_profile: &PermissionProfile,
|
|
||||||
) -> Result<Self> {
|
|
||||||
if !matches!(permission_profile, PermissionProfile::Managed { .. }) {
|
if !matches!(permission_profile, PermissionProfile::Managed { .. }) {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"only managed permission profiles can be enforced by the Windows sandbox"
|
"only managed permission profiles can be enforced by the Windows sandbox"
|
||||||
@@ -92,6 +90,26 @@ impl ResolvedWindowsSandboxPermissions {
|
|||||||
self.network
|
self.network
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_enforceable_by_windows_sandbox(&self) -> bool {
|
||||||
|
matches!(self.file_system.kind, FileSystemSandboxKind::Restricted)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_full_disk_read_access(&self) -> bool {
|
||||||
|
self.file_system.has_full_disk_read_access()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn include_platform_defaults(&self) -> bool {
|
||||||
|
self.file_system.include_platform_defaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn readable_roots_for_cwd(&self, cwd: &Path) -> Vec<PathBuf> {
|
||||||
|
self.file_system
|
||||||
|
.get_readable_roots_with_cwd(cwd)
|
||||||
|
.into_iter()
|
||||||
|
.map(AbsolutePathBuf::into_path_buf)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn uses_write_capabilities_for_cwd(
|
pub(crate) fn uses_write_capabilities_for_cwd(
|
||||||
&self,
|
&self,
|
||||||
cwd: &Path,
|
cwd: &Path,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use std::process::Command;
|
|||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
|
|
||||||
use crate::allow::AllowDenyPaths;
|
use crate::allow::AllowDenyPaths;
|
||||||
use crate::allow::compute_allow_paths;
|
use crate::allow::compute_allow_paths_for_permissions;
|
||||||
use crate::helper_materialization::bundled_executable_path_for_exe;
|
use crate::helper_materialization::bundled_executable_path_for_exe;
|
||||||
use crate::helper_materialization::helper_bin_dir;
|
use crate::helper_materialization::helper_bin_dir;
|
||||||
use crate::logging::log_note;
|
use crate::logging::log_note;
|
||||||
@@ -87,8 +87,7 @@ pub fn sandbox_users_path(codex_home: &Path) -> PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct SandboxSetupRequest<'a> {
|
pub struct SandboxSetupRequest<'a> {
|
||||||
pub policy: &'a SandboxPolicy,
|
pub permissions: &'a ResolvedWindowsSandboxPermissions,
|
||||||
pub policy_cwd: &'a Path,
|
|
||||||
pub command_cwd: &'a Path,
|
pub command_cwd: &'a Path,
|
||||||
pub env_map: &'a HashMap<String, String>,
|
pub env_map: &'a HashMap<String, String>,
|
||||||
pub codex_home: &'a Path,
|
pub codex_home: &'a Path,
|
||||||
@@ -112,10 +111,17 @@ pub fn run_setup_refresh(
|
|||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
proxy_enforced: bool,
|
proxy_enforced: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
if matches!(
|
||||||
|
policy,
|
||||||
|
SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. }
|
||||||
|
) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let permissions =
|
||||||
|
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(policy, policy_cwd);
|
||||||
run_setup_refresh_inner(
|
run_setup_refresh_inner(
|
||||||
SandboxSetupRequest {
|
SandboxSetupRequest {
|
||||||
policy,
|
permissions: &permissions,
|
||||||
policy_cwd,
|
|
||||||
command_cwd,
|
command_cwd,
|
||||||
env_map,
|
env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
@@ -141,12 +147,19 @@ pub fn run_setup_refresh_with_extra_read_roots(
|
|||||||
extra_read_roots: Vec<PathBuf>,
|
extra_read_roots: Vec<PathBuf>,
|
||||||
proxy_enforced: bool,
|
proxy_enforced: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut read_roots = gather_read_roots(command_cwd, policy, codex_home);
|
if matches!(
|
||||||
|
policy,
|
||||||
|
SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. }
|
||||||
|
) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let permissions =
|
||||||
|
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(policy, policy_cwd);
|
||||||
|
let mut read_roots = gather_read_roots(command_cwd, &permissions, env_map, codex_home);
|
||||||
read_roots.extend(extra_read_roots);
|
read_roots.extend(extra_read_roots);
|
||||||
run_setup_refresh_inner(
|
run_setup_refresh_inner(
|
||||||
SandboxSetupRequest {
|
SandboxSetupRequest {
|
||||||
policy,
|
permissions: &permissions,
|
||||||
policy_cwd,
|
|
||||||
command_cwd,
|
command_cwd,
|
||||||
env_map,
|
env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
@@ -166,22 +179,14 @@ fn run_setup_refresh_inner(
|
|||||||
request: SandboxSetupRequest<'_>,
|
request: SandboxSetupRequest<'_>,
|
||||||
overrides: SetupRootOverrides,
|
overrides: SetupRootOverrides,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Skip in danger-full-access.
|
if !request.permissions.is_enforceable_by_windows_sandbox() {
|
||||||
if matches!(
|
anyhow::bail!("unsupported filesystem permissions for Windows sandbox setup");
|
||||||
request.policy,
|
|
||||||
SandboxPolicy::DangerFullAccess | SandboxPolicy::ExternalSandbox { .. }
|
|
||||||
) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
let (read_roots, write_roots) = build_payload_roots(&request, &overrides);
|
let (read_roots, write_roots) = build_payload_roots(&request, &overrides);
|
||||||
let deny_read_paths = build_payload_deny_read_paths(overrides.deny_read_paths);
|
let deny_read_paths = build_payload_deny_read_paths(overrides.deny_read_paths);
|
||||||
let deny_write_paths = build_payload_deny_write_paths(&request, overrides.deny_write_paths);
|
let deny_write_paths = build_payload_deny_write_paths(&request, overrides.deny_write_paths);
|
||||||
let permissions = ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(
|
|
||||||
request.policy,
|
|
||||||
request.policy_cwd,
|
|
||||||
);
|
|
||||||
let network_identity =
|
let network_identity =
|
||||||
SandboxNetworkIdentity::from_permissions(&permissions, request.proxy_enforced);
|
SandboxNetworkIdentity::from_permissions(request.permissions, request.proxy_enforced);
|
||||||
let offline_proxy_settings = offline_proxy_settings_from_env(request.env_map, network_identity);
|
let offline_proxy_settings = offline_proxy_settings_from_env(request.env_map, network_identity);
|
||||||
let payload = ElevationPayload {
|
let payload = ElevationPayload {
|
||||||
version: SETUP_VERSION,
|
version: SETUP_VERSION,
|
||||||
@@ -365,9 +370,10 @@ fn gather_helper_read_roots(codex_home: &Path) -> Vec<PathBuf> {
|
|||||||
vec![helper_dir]
|
vec![helper_dir]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_legacy_full_read_roots(
|
fn gather_full_read_roots_for_permissions(
|
||||||
command_cwd: &Path,
|
command_cwd: &Path,
|
||||||
policy: &SandboxPolicy,
|
permissions: &ResolvedWindowsSandboxPermissions,
|
||||||
|
env_map: &HashMap<String, String>,
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
) -> Vec<PathBuf> {
|
) -> Vec<PathBuf> {
|
||||||
let mut roots = gather_helper_read_roots(codex_home);
|
let mut roots = gather_helper_read_roots(codex_home);
|
||||||
@@ -380,20 +386,40 @@ fn gather_legacy_full_read_roots(
|
|||||||
roots.extend(profile_read_roots(Path::new(&up)));
|
roots.extend(profile_read_roots(Path::new(&up)));
|
||||||
}
|
}
|
||||||
roots.push(command_cwd.to_path_buf());
|
roots.push(command_cwd.to_path_buf());
|
||||||
if let SandboxPolicy::WorkspaceWrite { writable_roots, .. } = policy {
|
roots.extend(
|
||||||
for root in writable_roots {
|
permissions
|
||||||
roots.push(root.to_path_buf());
|
.writable_roots_for_cwd(command_cwd, env_map)
|
||||||
}
|
.into_iter()
|
||||||
}
|
.map(|root| root.root),
|
||||||
|
);
|
||||||
canonical_existing(&roots)
|
canonical_existing(&roots)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn gather_read_roots(
|
pub(crate) fn gather_read_roots(
|
||||||
command_cwd: &Path,
|
command_cwd: &Path,
|
||||||
policy: &SandboxPolicy,
|
permissions: &ResolvedWindowsSandboxPermissions,
|
||||||
|
env_map: &HashMap<String, String>,
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
) -> Vec<PathBuf> {
|
) -> Vec<PathBuf> {
|
||||||
gather_legacy_full_read_roots(command_cwd, policy, codex_home)
|
if permissions.has_full_disk_read_access() {
|
||||||
|
return gather_full_read_roots_for_permissions(
|
||||||
|
command_cwd,
|
||||||
|
permissions,
|
||||||
|
env_map,
|
||||||
|
codex_home,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut roots = gather_helper_read_roots(codex_home);
|
||||||
|
if permissions.include_platform_defaults() {
|
||||||
|
roots.extend(
|
||||||
|
WINDOWS_PLATFORM_DEFAULT_READ_ROOTS
|
||||||
|
.iter()
|
||||||
|
.map(PathBuf::from),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
roots.extend(permissions.readable_roots_for_cwd(command_cwd));
|
||||||
|
canonical_existing(&roots)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn gather_write_roots_for_permissions(
|
pub(crate) fn gather_write_roots_for_permissions(
|
||||||
@@ -417,17 +443,14 @@ pub(crate) fn gather_write_roots_for_permissions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn effective_write_roots_for_setup(
|
pub(crate) fn effective_write_roots_for_setup(
|
||||||
policy: &SandboxPolicy,
|
permissions: &ResolvedWindowsSandboxPermissions,
|
||||||
policy_cwd: &Path,
|
|
||||||
command_cwd: &Path,
|
command_cwd: &Path,
|
||||||
env_map: &HashMap<String, String>,
|
env_map: &HashMap<String, String>,
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
write_roots_override: Option<&[PathBuf]>,
|
write_roots_override: Option<&[PathBuf]>,
|
||||||
) -> Vec<PathBuf> {
|
) -> Vec<PathBuf> {
|
||||||
let permissions =
|
|
||||||
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(policy, policy_cwd);
|
|
||||||
effective_write_roots_for_permissions(
|
effective_write_roots_for_permissions(
|
||||||
&permissions,
|
permissions,
|
||||||
command_cwd,
|
command_cwd,
|
||||||
env_map,
|
env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
@@ -753,6 +776,9 @@ pub fn run_elevated_setup(
|
|||||||
request: SandboxSetupRequest<'_>,
|
request: SandboxSetupRequest<'_>,
|
||||||
overrides: SetupRootOverrides,
|
overrides: SetupRootOverrides,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
if !request.permissions.is_enforceable_by_windows_sandbox() {
|
||||||
|
anyhow::bail!("unsupported filesystem permissions for Windows sandbox setup");
|
||||||
|
}
|
||||||
// Ensure the shared sandbox directory exists before we send it to the elevated helper.
|
// Ensure the shared sandbox directory exists before we send it to the elevated helper.
|
||||||
let sbx_dir = sandbox_dir(request.codex_home);
|
let sbx_dir = sandbox_dir(request.codex_home);
|
||||||
std::fs::create_dir_all(&sbx_dir).map_err(|err| {
|
std::fs::create_dir_all(&sbx_dir).map_err(|err| {
|
||||||
@@ -764,12 +790,8 @@ pub fn run_elevated_setup(
|
|||||||
let (read_roots, write_roots) = build_payload_roots(&request, &overrides);
|
let (read_roots, write_roots) = build_payload_roots(&request, &overrides);
|
||||||
let deny_read_paths = build_payload_deny_read_paths(overrides.deny_read_paths);
|
let deny_read_paths = build_payload_deny_read_paths(overrides.deny_read_paths);
|
||||||
let deny_write_paths = build_payload_deny_write_paths(&request, overrides.deny_write_paths);
|
let deny_write_paths = build_payload_deny_write_paths(&request, overrides.deny_write_paths);
|
||||||
let permissions = ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(
|
|
||||||
request.policy,
|
|
||||||
request.policy_cwd,
|
|
||||||
);
|
|
||||||
let network_identity =
|
let network_identity =
|
||||||
SandboxNetworkIdentity::from_permissions(&permissions, request.proxy_enforced);
|
SandboxNetworkIdentity::from_permissions(request.permissions, request.proxy_enforced);
|
||||||
let offline_proxy_settings = offline_proxy_settings_from_env(request.env_map, network_identity);
|
let offline_proxy_settings = offline_proxy_settings_from_env(request.env_map, network_identity);
|
||||||
let payload = ElevationPayload {
|
let payload = ElevationPayload {
|
||||||
version: SETUP_VERSION,
|
version: SETUP_VERSION,
|
||||||
@@ -801,8 +823,7 @@ fn build_payload_roots(
|
|||||||
overrides: &SetupRootOverrides,
|
overrides: &SetupRootOverrides,
|
||||||
) -> (Vec<PathBuf>, Vec<PathBuf>) {
|
) -> (Vec<PathBuf>, Vec<PathBuf>) {
|
||||||
let write_roots = effective_write_roots_for_setup(
|
let write_roots = effective_write_roots_for_setup(
|
||||||
request.policy,
|
request.permissions,
|
||||||
request.policy_cwd,
|
|
||||||
request.command_cwd,
|
request.command_cwd,
|
||||||
request.env_map,
|
request.env_map,
|
||||||
request.codex_home,
|
request.codex_home,
|
||||||
@@ -822,7 +843,12 @@ fn build_payload_roots(
|
|||||||
read_roots.extend(roots.iter().cloned());
|
read_roots.extend(roots.iter().cloned());
|
||||||
canonical_existing(&read_roots)
|
canonical_existing(&read_roots)
|
||||||
} else {
|
} else {
|
||||||
gather_read_roots(request.command_cwd, request.policy, request.codex_home)
|
gather_read_roots(
|
||||||
|
request.command_cwd,
|
||||||
|
request.permissions,
|
||||||
|
request.env_map,
|
||||||
|
request.codex_home,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
read_roots = expand_user_profile_root(read_roots);
|
read_roots = expand_user_profile_root(read_roots);
|
||||||
read_roots = filter_user_profile_root(read_roots);
|
read_roots = filter_user_profile_root(read_roots);
|
||||||
@@ -837,9 +863,8 @@ fn build_payload_deny_write_paths(
|
|||||||
request: &SandboxSetupRequest<'_>,
|
request: &SandboxSetupRequest<'_>,
|
||||||
explicit_deny_write_paths: Option<Vec<PathBuf>>,
|
explicit_deny_write_paths: Option<Vec<PathBuf>>,
|
||||||
) -> Vec<PathBuf> {
|
) -> Vec<PathBuf> {
|
||||||
let allow_deny_paths: AllowDenyPaths = compute_allow_paths(
|
let allow_deny_paths: AllowDenyPaths = compute_allow_paths_for_permissions(
|
||||||
request.policy,
|
request.permissions,
|
||||||
request.policy_cwd,
|
|
||||||
request.command_cwd,
|
request.command_cwd,
|
||||||
request.env_map,
|
request.env_map,
|
||||||
);
|
);
|
||||||
@@ -986,7 +1011,7 @@ mod tests {
|
|||||||
use super::WINDOWS_PLATFORM_DEFAULT_READ_ROOTS;
|
use super::WINDOWS_PLATFORM_DEFAULT_READ_ROOTS;
|
||||||
use super::build_payload_roots;
|
use super::build_payload_roots;
|
||||||
use super::find_setup_exe_for_current_exe;
|
use super::find_setup_exe_for_current_exe;
|
||||||
use super::gather_legacy_full_read_roots;
|
use super::gather_full_read_roots_for_permissions;
|
||||||
use super::gather_read_roots;
|
use super::gather_read_roots;
|
||||||
use super::loopback_proxy_port_from_url;
|
use super::loopback_proxy_port_from_url;
|
||||||
use super::offline_proxy_settings_from_env;
|
use super::offline_proxy_settings_from_env;
|
||||||
@@ -996,6 +1021,7 @@ mod tests {
|
|||||||
use crate::helper_materialization::RESOURCES_DIRNAME;
|
use crate::helper_materialization::RESOURCES_DIRNAME;
|
||||||
use crate::helper_materialization::helper_bin_dir;
|
use crate::helper_materialization::helper_bin_dir;
|
||||||
use crate::policy::SandboxPolicy;
|
use crate::policy::SandboxPolicy;
|
||||||
|
use crate::resolved_permissions::ResolvedWindowsSandboxPermissions;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -1011,6 +1037,13 @@ mod tests {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn permissions_for(
|
||||||
|
policy: &SandboxPolicy,
|
||||||
|
policy_cwd: &std::path::Path,
|
||||||
|
) -> ResolvedWindowsSandboxPermissions {
|
||||||
|
ResolvedWindowsSandboxPermissions::from_legacy_policy_for_cwd(policy, policy_cwd)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn loopback_proxy_url_parsing_supports_common_forms() {
|
fn loopback_proxy_url_parsing_supports_common_forms() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -1329,8 +1362,9 @@ mod tests {
|
|||||||
let command_cwd = tmp.path().join("workspace");
|
let command_cwd = tmp.path().join("workspace");
|
||||||
fs::create_dir_all(&command_cwd).expect("create workspace");
|
fs::create_dir_all(&command_cwd).expect("create workspace");
|
||||||
let policy = SandboxPolicy::new_read_only_policy();
|
let policy = SandboxPolicy::new_read_only_policy();
|
||||||
|
let permissions = permissions_for(&policy, &command_cwd);
|
||||||
|
|
||||||
let roots = gather_read_roots(&command_cwd, &policy, &codex_home);
|
let roots = gather_read_roots(&command_cwd, &permissions, &HashMap::new(), &codex_home);
|
||||||
let expected =
|
let expected =
|
||||||
dunce::canonicalize(helper_bin_dir(&codex_home)).expect("canonical helper dir");
|
dunce::canonicalize(helper_bin_dir(&codex_home)).expect("canonical helper dir");
|
||||||
|
|
||||||
@@ -1354,8 +1388,9 @@ mod tests {
|
|||||||
exclude_tmpdir_env_var: true,
|
exclude_tmpdir_env_var: true,
|
||||||
exclude_slash_tmp: true,
|
exclude_slash_tmp: true,
|
||||||
};
|
};
|
||||||
|
let permissions = permissions_for(&policy, &command_cwd);
|
||||||
|
|
||||||
let roots = gather_read_roots(&command_cwd, &policy, &codex_home);
|
let roots = gather_read_roots(&command_cwd, &permissions, &HashMap::new(), &codex_home);
|
||||||
let expected_writable =
|
let expected_writable =
|
||||||
dunce::canonicalize(&writable_root).expect("canonical writable root");
|
dunce::canonicalize(&writable_root).expect("canonical writable root");
|
||||||
|
|
||||||
@@ -1375,11 +1410,11 @@ mod tests {
|
|||||||
let policy = SandboxPolicy::ReadOnly {
|
let policy = SandboxPolicy::ReadOnly {
|
||||||
network_access: false,
|
network_access: false,
|
||||||
};
|
};
|
||||||
|
let permissions = permissions_for(&policy, &policy_cwd);
|
||||||
|
|
||||||
let (read_roots, write_roots) = build_payload_roots(
|
let (read_roots, write_roots) = build_payload_roots(
|
||||||
&super::SandboxSetupRequest {
|
&super::SandboxSetupRequest {
|
||||||
policy: &policy,
|
permissions: &permissions,
|
||||||
policy_cwd: &policy_cwd,
|
|
||||||
command_cwd: &command_cwd,
|
command_cwd: &command_cwd,
|
||||||
env_map: &HashMap::new(),
|
env_map: &HashMap::new(),
|
||||||
codex_home: &codex_home,
|
codex_home: &codex_home,
|
||||||
@@ -1423,11 +1458,11 @@ mod tests {
|
|||||||
let policy = SandboxPolicy::ReadOnly {
|
let policy = SandboxPolicy::ReadOnly {
|
||||||
network_access: false,
|
network_access: false,
|
||||||
};
|
};
|
||||||
|
let permissions = permissions_for(&policy, &policy_cwd);
|
||||||
|
|
||||||
let (read_roots, write_roots) = build_payload_roots(
|
let (read_roots, write_roots) = build_payload_roots(
|
||||||
&super::SandboxSetupRequest {
|
&super::SandboxSetupRequest {
|
||||||
policy: &policy,
|
permissions: &permissions,
|
||||||
policy_cwd: &policy_cwd,
|
|
||||||
command_cwd: &command_cwd,
|
command_cwd: &command_cwd,
|
||||||
env_map: &HashMap::new(),
|
env_map: &HashMap::new(),
|
||||||
codex_home: &codex_home,
|
codex_home: &codex_home,
|
||||||
@@ -1475,6 +1510,7 @@ mod tests {
|
|||||||
exclude_tmpdir_env_var: true,
|
exclude_tmpdir_env_var: true,
|
||||||
exclude_slash_tmp: true,
|
exclude_slash_tmp: true,
|
||||||
};
|
};
|
||||||
|
let permissions = permissions_for(&policy, &command_cwd);
|
||||||
let override_roots = vec![
|
let override_roots = vec![
|
||||||
command_cwd.clone(),
|
command_cwd.clone(),
|
||||||
extra_root.clone(),
|
extra_root.clone(),
|
||||||
@@ -1482,8 +1518,7 @@ mod tests {
|
|||||||
sandbox_root.clone(),
|
sandbox_root.clone(),
|
||||||
];
|
];
|
||||||
let request = super::SandboxSetupRequest {
|
let request = super::SandboxSetupRequest {
|
||||||
policy: &policy,
|
permissions: &permissions,
|
||||||
policy_cwd: &command_cwd,
|
|
||||||
command_cwd: &command_cwd,
|
command_cwd: &command_cwd,
|
||||||
env_map: &HashMap::new(),
|
env_map: &HashMap::new(),
|
||||||
codex_home: &codex_home,
|
codex_home: &codex_home,
|
||||||
@@ -1498,8 +1533,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let effective_write_roots = super::effective_write_roots_for_setup(
|
let effective_write_roots = super::effective_write_roots_for_setup(
|
||||||
&policy,
|
&permissions,
|
||||||
&command_cwd,
|
|
||||||
&command_cwd,
|
&command_cwd,
|
||||||
&HashMap::new(),
|
&HashMap::new(),
|
||||||
&codex_home,
|
&codex_home,
|
||||||
@@ -1533,10 +1567,10 @@ mod tests {
|
|||||||
exclude_tmpdir_env_var: true,
|
exclude_tmpdir_env_var: true,
|
||||||
exclude_slash_tmp: true,
|
exclude_slash_tmp: true,
|
||||||
};
|
};
|
||||||
|
let permissions = permissions_for(&policy, &policy_cwd);
|
||||||
|
|
||||||
let effective_write_roots = super::effective_write_roots_for_setup(
|
let effective_write_roots = super::effective_write_roots_for_setup(
|
||||||
&policy,
|
&permissions,
|
||||||
&policy_cwd,
|
|
||||||
&command_cwd,
|
&command_cwd,
|
||||||
&HashMap::new(),
|
&HashMap::new(),
|
||||||
&codex_home,
|
&codex_home,
|
||||||
@@ -1569,9 +1603,9 @@ mod tests {
|
|||||||
exclude_tmpdir_env_var: true,
|
exclude_tmpdir_env_var: true,
|
||||||
exclude_slash_tmp: true,
|
exclude_slash_tmp: true,
|
||||||
};
|
};
|
||||||
|
let permissions = permissions_for(&policy, &command_cwd);
|
||||||
let request = super::SandboxSetupRequest {
|
let request = super::SandboxSetupRequest {
|
||||||
policy: &policy,
|
permissions: &permissions,
|
||||||
policy_cwd: &command_cwd,
|
|
||||||
command_cwd: &command_cwd,
|
command_cwd: &command_cwd,
|
||||||
env_map: &HashMap::new(),
|
env_map: &HashMap::new(),
|
||||||
codex_home: &codex_home,
|
codex_home: &codex_home,
|
||||||
@@ -1600,8 +1634,14 @@ mod tests {
|
|||||||
let command_cwd = tmp.path().join("workspace");
|
let command_cwd = tmp.path().join("workspace");
|
||||||
fs::create_dir_all(&command_cwd).expect("create workspace");
|
fs::create_dir_all(&command_cwd).expect("create workspace");
|
||||||
let policy = SandboxPolicy::new_read_only_policy();
|
let policy = SandboxPolicy::new_read_only_policy();
|
||||||
|
let permissions = permissions_for(&policy, &command_cwd);
|
||||||
|
|
||||||
let roots = gather_legacy_full_read_roots(&command_cwd, &policy, &codex_home);
|
let roots = gather_full_read_roots_for_permissions(
|
||||||
|
&command_cwd,
|
||||||
|
&permissions,
|
||||||
|
&HashMap::new(),
|
||||||
|
&codex_home,
|
||||||
|
);
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
canonical_windows_platform_default_roots()
|
canonical_windows_platform_default_roots()
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use crate::acl::add_allow_ace;
|
|||||||
use crate::acl::add_deny_write_ace;
|
use crate::acl::add_deny_write_ace;
|
||||||
use crate::acl::allow_null_device;
|
use crate::acl::allow_null_device;
|
||||||
use crate::allow::AllowDenyPaths;
|
use crate::allow::AllowDenyPaths;
|
||||||
use crate::allow::compute_allow_paths;
|
|
||||||
use crate::allow::compute_allow_paths_for_permissions;
|
use crate::allow::compute_allow_paths_for_permissions;
|
||||||
use crate::cap::load_or_create_cap_sids;
|
use crate::cap::load_or_create_cap_sids;
|
||||||
use crate::cap::workspace_write_cap_sid_for_root;
|
use crate::cap::workspace_write_cap_sid_for_root;
|
||||||
@@ -283,8 +282,7 @@ pub(crate) fn allow_null_device_for_workspace_write(is_workspace_write: bool) {
|
|||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn apply_legacy_session_acl_rules(
|
pub(crate) fn apply_legacy_session_acl_rules(
|
||||||
policy: &SandboxPolicy,
|
permissions: &ResolvedWindowsSandboxPermissions,
|
||||||
sandbox_policy_cwd: &Path,
|
|
||||||
codex_home: &Path,
|
codex_home: &Path,
|
||||||
current_dir: &Path,
|
current_dir: &Path,
|
||||||
env_map: &HashMap<String, String>,
|
env_map: &HashMap<String, String>,
|
||||||
@@ -293,7 +291,7 @@ pub(crate) fn apply_legacy_session_acl_rules(
|
|||||||
acl_sids: LegacyAclSids<'_>,
|
acl_sids: LegacyAclSids<'_>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let AllowDenyPaths { allow, mut deny } =
|
let AllowDenyPaths { allow, mut deny } =
|
||||||
compute_allow_paths(policy, sandbox_policy_cwd, current_dir, env_map);
|
compute_allow_paths_for_permissions(permissions, current_dir, env_map);
|
||||||
unsafe {
|
unsafe {
|
||||||
for path in additional_deny_write_paths {
|
for path in additional_deny_write_paths {
|
||||||
// Explicit carveouts must exist before the command starts so the
|
// Explicit carveouts must exist before the command starts so the
|
||||||
@@ -417,8 +415,7 @@ pub(crate) fn prepare_elevated_spawn_context(
|
|||||||
write_roots_override
|
write_roots_override
|
||||||
};
|
};
|
||||||
let sandbox_creds = require_logon_sandbox_creds(
|
let sandbox_creds = require_logon_sandbox_creds(
|
||||||
&common.policy,
|
&common.permissions,
|
||||||
sandbox_policy_cwd,
|
|
||||||
cwd,
|
cwd,
|
||||||
env_map,
|
env_map,
|
||||||
codex_home,
|
codex_home,
|
||||||
|
|||||||
@@ -318,8 +318,7 @@ pub(crate) async fn spawn_windows_sandbox_session_legacy(
|
|||||||
allow_null_device_for_workspace_write(common.uses_write_capabilities);
|
allow_null_device_for_workspace_write(common.uses_write_capabilities);
|
||||||
|
|
||||||
apply_legacy_session_acl_rules(
|
apply_legacy_session_acl_rules(
|
||||||
&common.policy,
|
&common.permissions,
|
||||||
sandbox_policy_cwd,
|
|
||||||
codex_home,
|
codex_home,
|
||||||
&common.current_dir,
|
&common.current_dir,
|
||||||
&env_map,
|
&env_map,
|
||||||
|
|||||||
Reference in new issue
Block a user