mirror of
https://github.com/openai/codex.git
synced 2026-09-08 15:50:34 +00:00
fix(windows): normalize sandbox cwd for mapped drives
This commit is contained in:
@@ -35,7 +35,9 @@ use codex_windows_sandbox::encode_bytes;
|
||||
use codex_windows_sandbox::get_current_token_for_restriction;
|
||||
use codex_windows_sandbox::hide_current_user_profile_dir;
|
||||
use codex_windows_sandbox::log_note;
|
||||
use codex_windows_sandbox::normalize_spawn_cwd;
|
||||
use codex_windows_sandbox::parse_policy;
|
||||
use codex_windows_sandbox::path_uses_unc_prefix;
|
||||
use codex_windows_sandbox::read_frame;
|
||||
use codex_windows_sandbox::read_handle_loop;
|
||||
use codex_windows_sandbox::spawn_process_with_pipes;
|
||||
@@ -167,6 +169,21 @@ fn read_spawn_request(reader: &mut File) -> Result<SpawnRequest> {
|
||||
|
||||
/// Pick an effective CWD, using a junction if the ACL helper is active.
|
||||
fn effective_cwd(req_cwd: &Path, log_dir: Option<&Path>) -> PathBuf {
|
||||
let normalized_cwd = normalize_spawn_cwd(req_cwd);
|
||||
if path_uses_unc_prefix(&normalized_cwd) {
|
||||
if normalized_cwd != req_cwd {
|
||||
log_note(
|
||||
&format!(
|
||||
"junction: using UNC cwd {} resolved from {}",
|
||||
normalized_cwd.display(),
|
||||
req_cwd.display()
|
||||
),
|
||||
log_dir,
|
||||
);
|
||||
}
|
||||
return normalized_cwd;
|
||||
}
|
||||
|
||||
let use_junction = match read_acl_mutex::read_acl_mutex_exists() {
|
||||
Ok(exists) => exists,
|
||||
Err(err) => {
|
||||
@@ -180,9 +197,10 @@ fn effective_cwd(req_cwd: &Path, log_dir: Option<&Path>) -> PathBuf {
|
||||
}
|
||||
};
|
||||
if use_junction {
|
||||
cwd_junction::create_cwd_junction(req_cwd, log_dir).unwrap_or_else(|| req_cwd.to_path_buf())
|
||||
cwd_junction::create_cwd_junction(req_cwd, log_dir)
|
||||
.unwrap_or_else(|| normalized_cwd.clone())
|
||||
} else {
|
||||
req_cwd.to_path_buf()
|
||||
normalized_cwd
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +149,10 @@ pub use logging::log_note;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use path_normalization::canonicalize_path;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use path_normalization::normalize_spawn_cwd;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use path_normalization::path_uses_unc_prefix;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use policy::SandboxPolicy;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use policy::parse_policy;
|
||||
|
||||
@@ -1,10 +1,32 @@
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::path::Prefix;
|
||||
|
||||
pub fn canonicalize_path(path: &Path) -> PathBuf {
|
||||
dunce::canonicalize(path).unwrap_or_else(|_| path.to_path_buf())
|
||||
}
|
||||
|
||||
pub fn normalize_spawn_cwd(path: &Path) -> PathBuf {
|
||||
let simplified = dunce::simplified(path).to_path_buf();
|
||||
if path_uses_unc_prefix(&simplified) {
|
||||
return simplified;
|
||||
}
|
||||
|
||||
let canonical = dunce::canonicalize(path).ok();
|
||||
let canonical = canonical
|
||||
.as_deref()
|
||||
.map(dunce::simplified)
|
||||
.map(Path::to_path_buf);
|
||||
if let Some(canonical) = canonical
|
||||
&& path_uses_unc_prefix(&canonical)
|
||||
{
|
||||
return canonical;
|
||||
}
|
||||
|
||||
simplified
|
||||
}
|
||||
|
||||
pub fn canonical_path_key(path: &Path) -> String {
|
||||
canonicalize_path(path)
|
||||
.to_string_lossy()
|
||||
@@ -12,17 +34,67 @@ pub fn canonical_path_key(path: &Path) -> String {
|
||||
.to_ascii_lowercase()
|
||||
}
|
||||
|
||||
pub fn path_uses_unc_prefix(path: &Path) -> bool {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
matches!(
|
||||
path.components().next(),
|
||||
Some(std::path::Component::Prefix(prefix))
|
||||
if matches!(prefix.kind(), Prefix::UNC(..) | Prefix::VerbatimUNC(..))
|
||||
)
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
let _ = path;
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::canonical_path_key;
|
||||
use super::normalize_spawn_cwd;
|
||||
use super::path_uses_unc_prefix;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
fn canonical_path_key_normalizes_case_and_separators() {
|
||||
let windows_style = Path::new(r"C:\Users\Dev\Repo");
|
||||
let slash_style = Path::new("c:/users/dev/repo");
|
||||
|
||||
assert_eq!(canonical_path_key(windows_style), canonical_path_key(slash_style));
|
||||
assert_eq!(
|
||||
canonical_path_key(windows_style),
|
||||
canonical_path_key(slash_style)
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[test]
|
||||
fn path_uses_unc_prefix_matches_standard_and_verbatim_unc_paths() {
|
||||
assert!(path_uses_unc_prefix(Path::new(r"\\server\share\repo")));
|
||||
assert!(path_uses_unc_prefix(Path::new(
|
||||
r"\\?\UNC\server\share\repo"
|
||||
)));
|
||||
assert!(!path_uses_unc_prefix(Path::new(r"C:\repo")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_spawn_cwd_preserves_regular_local_paths() {
|
||||
let path = PathBuf::from(r"C:\repo");
|
||||
|
||||
assert_eq!(normalize_spawn_cwd(&path), path);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[test]
|
||||
fn normalize_spawn_cwd_simplifies_verbatim_unc_paths() {
|
||||
let path = PathBuf::from(r"\\?\UNC\server\share\repo");
|
||||
|
||||
assert_eq!(
|
||||
normalize_spawn_cwd(&path),
|
||||
PathBuf::from(r"\\server\share\repo")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
use crate::desktop::LaunchDesktop;
|
||||
use crate::logging;
|
||||
use crate::path_normalization::normalize_spawn_cwd;
|
||||
use crate::proc_thread_attr::ProcThreadAttributeList;
|
||||
use crate::winutil::argv_to_command_line;
|
||||
use crate::winutil::format_last_error;
|
||||
use crate::winutil::to_wide;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Result;
|
||||
use anyhow::anyhow;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::c_void;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use windows_sys::Win32::Foundation::GetLastError;
|
||||
use windows_sys::Win32::Foundation::CloseHandle;
|
||||
use windows_sys::Win32::Foundation::SetHandleInformation;
|
||||
use windows_sys::Win32::Foundation::GetLastError;
|
||||
use windows_sys::Win32::Foundation::HANDLE;
|
||||
use windows_sys::Win32::Foundation::HANDLE_FLAG_INHERIT;
|
||||
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
|
||||
use windows_sys::Win32::Foundation::SetHandleInformation;
|
||||
use windows_sys::Win32::Storage::FileSystem::ReadFile;
|
||||
use windows_sys::Win32::System::Console::GetStdHandle;
|
||||
use windows_sys::Win32::System::Console::STD_ERROR_HANDLE;
|
||||
use windows_sys::Win32::System::Console::STD_INPUT_HANDLE;
|
||||
use windows_sys::Win32::System::Console::STD_OUTPUT_HANDLE;
|
||||
use windows_sys::Win32::System::Pipes::CreatePipe;
|
||||
use windows_sys::Win32::System::Threading::CreateProcessAsUserW;
|
||||
use windows_sys::Win32::System::Threading::CREATE_UNICODE_ENVIRONMENT;
|
||||
use windows_sys::Win32::System::Threading::CreateProcessAsUserW;
|
||||
use windows_sys::Win32::System::Threading::EXTENDED_STARTUPINFO_PRESENT;
|
||||
use windows_sys::Win32::System::Threading::PROCESS_INFORMATION;
|
||||
use windows_sys::Win32::System::Threading::STARTF_USESTDHANDLES;
|
||||
@@ -89,7 +90,8 @@ pub unsafe fn create_process_as_user(
|
||||
let env_block = make_env_block(env_map);
|
||||
let desktop = LaunchDesktop::prepare(use_private_desktop, logs_base_dir)?;
|
||||
let mut pi: PROCESS_INFORMATION = std::mem::zeroed();
|
||||
let cwd_wide = to_wide(cwd);
|
||||
let spawn_cwd = normalize_spawn_cwd(cwd);
|
||||
let cwd_wide = to_wide(&spawn_cwd);
|
||||
let env_block_len = env_block.len();
|
||||
match stdio {
|
||||
Some((stdin_h, stdout_h, stderr_h)) => {
|
||||
@@ -139,7 +141,7 @@ pub unsafe fn create_process_as_user(
|
||||
"CreateProcessAsUserW failed: {} ({}) | cwd={} | cmd={} | env_u16_len={} | si_flags={} | creation_flags={}",
|
||||
err,
|
||||
format_last_error(err),
|
||||
cwd.display(),
|
||||
spawn_cwd.display(),
|
||||
cmdline_str,
|
||||
env_block_len,
|
||||
si.StartupInfo.dwFlags,
|
||||
@@ -180,7 +182,7 @@ pub unsafe fn create_process_as_user(
|
||||
"CreateProcessAsUserW failed: {} ({}) | cwd={} | cmd={} | env_u16_len={} | si_flags={} | creation_flags={}",
|
||||
err,
|
||||
format_last_error(err),
|
||||
cwd.display(),
|
||||
spawn_cwd.display(),
|
||||
cmdline_str,
|
||||
env_block_len,
|
||||
si.dwFlags,
|
||||
|
||||
Reference in New Issue
Block a user