chore: move pty and windows sandbox to Rust 2024 (#15954)

## Why

`codex-utils-pty` and `codex-windows-sandbox` were the remaining crates
in `codex-rs` that still overrode the workspace's Rust 2024 edition.
Moving them forward in a separate PR keeps the baseline edition update
isolated from the follow-on Bazel clippy workflow in #15955, while
making linting and formatting behavior consistent with the rest of the
workspace.

This PR also needs Cargo and Bazel to agree on the edition for
`codex-windows-sandbox`. Without the Bazel-side sync, the experimental
Bazel app-server builds fail once they compile `windows-sandbox-rs`.

## What changed

- switch `codex-rs/utils/pty` and `codex-rs/windows-sandbox-rs` to
`edition = "2024"`
- update `codex-utils-pty` callsites and tests to use the collapsed `if
let` form that Clippy expects under the new edition
- fix the Rust 2024 fallout in `windows-sandbox-rs`, including the
reserved `gen` identifier, `unsafe extern` requirements, and new Clippy
findings that surfaced under the edition bump
- keep the edition bump separate from a larger unsafe cleanup by
temporarily allowing `unsafe_op_in_unsafe_fn` in the Windows entrypoint
modules that now report it under Rust 2024
- update `codex-rs/windows-sandbox-rs/BUILD.bazel` to `crate_edition =
"2024"` so Bazel compiles the crate with the same edition as Cargo





---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/15954).
* #15976
* #15955
* __->__ #15954
This commit is contained in:
Michael Bolin authored and GitHub committed 2026-03-27 02:31:08 -07:00
1 parent 2e849703cd
commit 2ef91b7140
30 files changed
+255 -248

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
[package] [package]
edition = "2021" edition = "2024"
license.workspace = true license.workspace = true
name = "codex-utils-pty" name = "codex-utils-pty"
version.workspace = true version.workspace = true
+2 -2
View File
@@ -13,14 +13,14 @@ pub const DEFAULT_OUTPUT_BYTES_CAP: usize = 1024 * 1024;
pub use pipe::spawn_process as spawn_pipe_process; pub use pipe::spawn_process as spawn_pipe_process;
/// Spawn a non-interactive process using regular pipes, but close stdin immediately. /// Spawn a non-interactive process using regular pipes, but close stdin immediately.
pub use pipe::spawn_process_no_stdin as spawn_pipe_process_no_stdin; pub use pipe::spawn_process_no_stdin as spawn_pipe_process_no_stdin;
/// Combine stdout/stderr receivers into a single broadcast receiver.
pub use process::combine_output_receivers;
/// Handle for interacting with a spawned process (PTY or pipe). /// Handle for interacting with a spawned process (PTY or pipe).
pub use process::ProcessHandle; pub use process::ProcessHandle;
/// Bundle of process handles plus split output and exit receivers returned by spawn helpers. /// Bundle of process handles plus split output and exit receivers returned by spawn helpers.
pub use process::SpawnedProcess; pub use process::SpawnedProcess;
/// Terminal size in character cells used for PTY spawn and resize operations. /// Terminal size in character cells used for PTY spawn and resize operations.
pub use process::TerminalSize; pub use process::TerminalSize;
/// Combine stdout/stderr receivers into a single broadcast receiver.
pub use process::combine_output_receivers;
/// Backwards-compatible alias for ProcessHandle. /// Backwards-compatible alias for ProcessHandle.
pub type ExecCommandSession = ProcessHandle; pub type ExecCommandSession = ProcessHandle;
/// Backwards-compatible alias for SpawnedProcess. /// Backwards-compatible alias for SpawnedProcess.
+2 -6
View File
@@ -3,9 +3,9 @@ use std::io;
use std::io::ErrorKind; use std::io::ErrorKind;
use std::path::Path; use std::path::Path;
use std::process::Stdio; use std::process::Stdio;
use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex as StdMutex; use std::sync::Mutex as StdMutex;
use std::sync::atomic::AtomicBool;
use anyhow::Result; use anyhow::Result;
use tokio::io::AsyncRead; use tokio::io::AsyncRead;
@@ -64,11 +64,7 @@ fn kill_process(pid: u32) -> io::Result<()> {
let success = winapi::um::processthreadsapi::TerminateProcess(handle, 1); let success = winapi::um::processthreadsapi::TerminateProcess(handle, 1);
let err = io::Error::last_os_error(); let err = io::Error::last_os_error();
winapi::um::handleapi::CloseHandle(handle); winapi::um::handleapi::CloseHandle(handle);
if success == 0 { if success == 0 { Err(err) } else { Ok(()) }
Err(err)
} else {
Ok(())
}
} }
} }
+21 -21
View File
@@ -2,9 +2,9 @@ use core::fmt;
use std::io; use std::io;
#[cfg(unix)] #[cfg(unix)]
use std::os::fd::RawFd; use std::os::fd::RawFd;
use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex as StdMutex; use std::sync::Mutex as StdMutex;
use std::sync::atomic::AtomicBool;
use anyhow::anyhow; use anyhow::anyhow;
use portable_pty::MasterPty; use portable_pty::MasterPty;
@@ -118,10 +118,10 @@ impl ProcessHandle {
/// Returns a channel sender for writing raw bytes to the child stdin. /// Returns a channel sender for writing raw bytes to the child stdin.
pub fn writer_sender(&self) -> mpsc::Sender<Vec<u8>> { pub fn writer_sender(&self) -> mpsc::Sender<Vec<u8>> {
if let Ok(writer_tx) = self.writer_tx.lock() { if let Ok(writer_tx) = self.writer_tx.lock()
if let Some(writer_tx) = writer_tx.as_ref() { && let Some(writer_tx) = writer_tx.as_ref()
return writer_tx.clone(); {
} return writer_tx.clone();
} }
let (writer_tx, writer_rx) = mpsc::channel(1); let (writer_tx, writer_rx) = mpsc::channel(1);
@@ -165,10 +165,10 @@ impl ProcessHandle {
/// Attempts to kill the child while leaving the reader/writer tasks alive /// Attempts to kill the child while leaving the reader/writer tasks alive
/// so callers can still drain output until EOF. /// so callers can still drain output until EOF.
pub fn request_terminate(&self) { pub fn request_terminate(&self) {
if let Ok(mut killer_opt) = self.killer.lock() { if let Ok(mut killer_opt) = self.killer.lock()
if let Some(mut killer) = killer_opt.take() { && let Some(mut killer) = killer_opt.take()
let _ = killer.kill(); {
} let _ = killer.kill();
} }
} }
@@ -176,25 +176,25 @@ impl ProcessHandle {
pub fn terminate(&self) { pub fn terminate(&self) {
self.request_terminate(); self.request_terminate();
if let Ok(mut h) = self.reader_handle.lock() { if let Ok(mut h) = self.reader_handle.lock()
if let Some(handle) = h.take() { && let Some(handle) = h.take()
handle.abort(); {
} handle.abort();
} }
if let Ok(mut handles) = self.reader_abort_handles.lock() { if let Ok(mut handles) = self.reader_abort_handles.lock() {
for handle in handles.drain(..) { for handle in handles.drain(..) {
handle.abort(); handle.abort();
} }
} }
if let Ok(mut h) = self.writer_handle.lock() { if let Ok(mut h) = self.writer_handle.lock()
if let Some(handle) = h.take() { && let Some(handle) = h.take()
handle.abort(); {
} handle.abort();
} }
if let Ok(mut h) = self.wait_handle.lock() { if let Ok(mut h) = self.wait_handle.lock()
if let Some(handle) = h.take() { && let Some(handle) = h.take()
handle.abort(); {
} handle.abort();
} }
} }
} }
+2 -2
View File
@@ -15,15 +15,15 @@ use std::path::Path;
use std::process::Command as StdCommand; use std::process::Command as StdCommand;
#[cfg(unix)] #[cfg(unix)]
use std::process::Stdio; use std::process::Stdio;
use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex as StdMutex; use std::sync::Mutex as StdMutex;
use std::sync::atomic::AtomicBool;
use std::time::Duration; use std::time::Duration;
use anyhow::Result; use anyhow::Result;
use portable_pty::CommandBuilder;
#[cfg(not(windows))] #[cfg(not(windows))]
use portable_pty::native_pty_system; use portable_pty::native_pty_system;
use portable_pty::CommandBuilder;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
+5 -7
View File
@@ -3,6 +3,8 @@ use std::path::Path;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use crate::SpawnedProcess;
use crate::TerminalSize;
use crate::combine_output_receivers; use crate::combine_output_receivers;
#[cfg(unix)] #[cfg(unix)]
use crate::pipe::spawn_process_no_stdin_with_inherited_fds; use crate::pipe::spawn_process_no_stdin_with_inherited_fds;
@@ -11,18 +13,15 @@ use crate::pty::spawn_process_with_inherited_fds;
use crate::spawn_pipe_process; use crate::spawn_pipe_process;
use crate::spawn_pipe_process_no_stdin; use crate::spawn_pipe_process_no_stdin;
use crate::spawn_pty_process; use crate::spawn_pty_process;
use crate::SpawnedProcess;
use crate::TerminalSize;
fn find_python() -> Option<String> { fn find_python() -> Option<String> {
for candidate in ["python3", "python"] { for candidate in ["python3", "python"] {
if let Ok(output) = std::process::Command::new(candidate) if let Ok(output) = std::process::Command::new(candidate)
.arg("--version") .arg("--version")
.output() .output()
&& output.status.success()
{ {
if output.status.success() { return Some(candidate.to_string());
return Some(candidate.to_string());
}
} }
} }
None None
@@ -855,8 +854,7 @@ async fn pty_spawn_with_inherited_fds_supports_resize() -> anyhow::Result<()> {
let write_end = unsafe { std::fs::File::from_raw_fd(fds[1]) }; let write_end = unsafe { std::fs::File::from_raw_fd(fds[1]) };
let env_map: HashMap<String, String> = std::env::vars().collect(); let env_map: HashMap<String, String> = std::env::vars().collect();
let script = let script = "stty -echo; printf 'start:%s\\n' \"$(stty size)\"; IFS= read _line; printf 'after:%s\\n' \"$(stty size)\"";
"stty -echo; printf 'start:%s\\n' \"$(stty size)\"; IFS= read _line; printf 'after:%s\\n' \"$(stty size)\"";
let spawned = spawn_process_with_inherited_fds( let spawned = spawn_process_with_inherited_fds(
"/bin/sh", "/bin/sh",
&["-c".to_string(), script.to_string()], &["-c".to_string(), script.to_string()],
+1 -1
View File
@@ -22,13 +22,13 @@ use crate::win::psuedocon::PsuedoCon;
use anyhow::Error; use anyhow::Error;
use filedescriptor::FileDescriptor; use filedescriptor::FileDescriptor;
use filedescriptor::Pipe; use filedescriptor::Pipe;
use portable_pty::cmdbuilder::CommandBuilder;
use portable_pty::Child; use portable_pty::Child;
use portable_pty::MasterPty; use portable_pty::MasterPty;
use portable_pty::PtyPair; use portable_pty::PtyPair;
use portable_pty::PtySize; use portable_pty::PtySize;
use portable_pty::PtySystem; use portable_pty::PtySystem;
use portable_pty::SlavePty; use portable_pty::SlavePty;
use portable_pty::cmdbuilder::CommandBuilder;
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use std::os::windows::io::AsRawHandle; use std::os::windows::io::AsRawHandle;
use std::os::windows::io::RawHandle; use std::os::windows::io::RawHandle;
+1 -5
View File
@@ -142,11 +142,7 @@ impl Child for WinChild {
fn process_id(&self) -> Option<u32> { fn process_id(&self) -> Option<u32> {
let res = unsafe { GetProcessId(self.proc.lock().unwrap().as_raw_handle() as _) }; let res = unsafe { GetProcessId(self.proc.lock().unwrap().as_raw_handle() as _) };
if res == 0 { if res == 0 { None } else { Some(res) }
None
} else {
Some(res)
}
} }
fn as_raw_handle(&self) -> Option<std::os::windows::io::RawHandle> { fn as_raw_handle(&self) -> Option<std::os::windows::io::RawHandle> {
+1 -1
View File
@@ -19,8 +19,8 @@
// SOFTWARE. // SOFTWARE.
use super::psuedocon::HPCON; use super::psuedocon::HPCON;
use anyhow::ensure;
use anyhow::Error; use anyhow::Error;
use anyhow::ensure;
use std::io::Error as IoError; use std::io::Error as IoError;
use std::mem; use std::mem;
use std::ptr; use std::ptr;
+2 -2
View File
@@ -21,9 +21,9 @@
use super::WinChild; use super::WinChild;
use crate::win::procthreadattr::ProcThreadAttributeList; use crate::win::procthreadattr::ProcThreadAttributeList;
use anyhow::Error;
use anyhow::bail; use anyhow::bail;
use anyhow::ensure; use anyhow::ensure;
use anyhow::Error;
use filedescriptor::FileDescriptor; use filedescriptor::FileDescriptor;
use filedescriptor::OwnedHandle; use filedescriptor::OwnedHandle;
use lazy_static::lazy_static; use lazy_static::lazy_static;
@@ -356,8 +356,8 @@ fn append_quoted(arg: &OsStr, cmdline: &mut Vec<u16>) {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::windows_build_number;
use super::MIN_CONPTY_BUILD; use super::MIN_CONPTY_BUILD;
use super::windows_build_number;
#[test] #[test]
fn windows_build_number_returns_value() { fn windows_build_number_returns_value() {
-1
View File
@@ -7,5 +7,4 @@ codex_rust_crate(
"Cargo.toml", "Cargo.toml",
"codex-windows-sandbox-setup.manifest", "codex-windows-sandbox-setup.manifest",
], ],
crate_edition = "2021",
) )
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
build = "build.rs" build = "build.rs"
edition = "2021" edition = "2024"
license.workspace = true license.workspace = true
name = "codex-windows-sandbox" name = "codex-windows-sandbox"
version.workspace = true version.workspace = true
+4 -4
View File
@@ -33,10 +33,10 @@ const SKIP_DIR_SUFFIXES: &[&str] = &[
]; ];
fn unique_push(set: &mut HashSet<PathBuf>, out: &mut Vec<PathBuf>, p: PathBuf) { fn unique_push(set: &mut HashSet<PathBuf>, out: &mut Vec<PathBuf>, p: PathBuf) {
if let Ok(abs) = p.canonicalize() { if let Ok(abs) = p.canonicalize()
if set.insert(abs.clone()) { && set.insert(abs.clone())
out.push(abs); {
} out.push(abs);
} }
} }
@@ -23,8 +23,8 @@ use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE; use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
use windows_sys::Win32::System::Console::ClosePseudoConsole; use windows_sys::Win32::System::Console::ClosePseudoConsole;
use windows_sys::Win32::System::Threading::CreateProcessAsUserW;
use windows_sys::Win32::System::Threading::CREATE_UNICODE_ENVIRONMENT; 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::EXTENDED_STARTUPINFO_PRESENT;
use windows_sys::Win32::System::Threading::PROCESS_INFORMATION; use windows_sys::Win32::System::Threading::PROCESS_INFORMATION;
use windows_sys::Win32::System::Threading::STARTF_USESTDHANDLES; use windows_sys::Win32::System::Threading::STARTF_USESTDHANDLES;
@@ -8,8 +8,8 @@ use std::io;
use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::System::Threading::DeleteProcThreadAttributeList; use windows_sys::Win32::System::Threading::DeleteProcThreadAttributeList;
use windows_sys::Win32::System::Threading::InitializeProcThreadAttributeList; use windows_sys::Win32::System::Threading::InitializeProcThreadAttributeList;
use windows_sys::Win32::System::Threading::UpdateProcThreadAttribute;
use windows_sys::Win32::System::Threading::LPPROC_THREAD_ATTRIBUTE_LIST; use windows_sys::Win32::System::Threading::LPPROC_THREAD_ATTRIBUTE_LIST;
use windows_sys::Win32::System::Threading::UpdateProcThreadAttribute;
const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: usize = 0x00020016; const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: usize = 0x00020016;
+1 -1
View File
@@ -89,7 +89,7 @@ struct PrivateDesktop {
impl PrivateDesktop { impl PrivateDesktop {
fn create(logs_base_dir: Option<&Path>) -> Result<Self> { fn create(logs_base_dir: Option<&Path>) -> Result<Self> {
let mut rng = SmallRng::from_entropy(); let mut rng = SmallRng::from_entropy();
let name = format!("CodexSandboxDesktop-{:x}", rng.gen::<u128>()); let name = format!("CodexSandboxDesktop-{:x}", rng.r#gen::<u128>());
let name_wide = to_wide(&name); let name_wide = to_wide(&name);
let handle = unsafe { let handle = unsafe {
CreateDesktopW( CreateDesktopW(
@@ -8,34 +8,35 @@
//! path spawns the child directly and does not use this runner. //! path spawns the child directly and does not use this runner.
#![cfg(target_os = "windows")] #![cfg(target_os = "windows")]
#![allow(unsafe_op_in_unsafe_fn)]
use anyhow::Context; use anyhow::Context;
use anyhow::Result; use anyhow::Result;
use codex_windows_sandbox::PipeSpawnHandles;
use codex_windows_sandbox::SandboxPolicy;
use codex_windows_sandbox::StderrMode;
use codex_windows_sandbox::StdinMode;
use codex_windows_sandbox::allow_null_device; use codex_windows_sandbox::allow_null_device;
use codex_windows_sandbox::convert_string_sid_to_sid; use codex_windows_sandbox::convert_string_sid_to_sid;
use codex_windows_sandbox::create_readonly_token_with_caps_from; use codex_windows_sandbox::create_readonly_token_with_caps_from;
use codex_windows_sandbox::create_workspace_write_token_with_caps_from; use codex_windows_sandbox::create_workspace_write_token_with_caps_from;
use codex_windows_sandbox::get_current_token_for_restriction; use codex_windows_sandbox::get_current_token_for_restriction;
use codex_windows_sandbox::hide_current_user_profile_dir; use codex_windows_sandbox::hide_current_user_profile_dir;
use codex_windows_sandbox::ipc_framed::decode_bytes;
use codex_windows_sandbox::ipc_framed::encode_bytes;
use codex_windows_sandbox::ipc_framed::read_frame;
use codex_windows_sandbox::ipc_framed::write_frame;
use codex_windows_sandbox::ipc_framed::ErrorPayload; use codex_windows_sandbox::ipc_framed::ErrorPayload;
use codex_windows_sandbox::ipc_framed::ExitPayload; use codex_windows_sandbox::ipc_framed::ExitPayload;
use codex_windows_sandbox::ipc_framed::FramedMessage; use codex_windows_sandbox::ipc_framed::FramedMessage;
use codex_windows_sandbox::ipc_framed::Message; use codex_windows_sandbox::ipc_framed::Message;
use codex_windows_sandbox::ipc_framed::OutputPayload; use codex_windows_sandbox::ipc_framed::OutputPayload;
use codex_windows_sandbox::ipc_framed::OutputStream; use codex_windows_sandbox::ipc_framed::OutputStream;
use codex_windows_sandbox::ipc_framed::decode_bytes;
use codex_windows_sandbox::ipc_framed::encode_bytes;
use codex_windows_sandbox::ipc_framed::read_frame;
use codex_windows_sandbox::ipc_framed::write_frame;
use codex_windows_sandbox::log_note; use codex_windows_sandbox::log_note;
use codex_windows_sandbox::parse_policy; use codex_windows_sandbox::parse_policy;
use codex_windows_sandbox::read_handle_loop; use codex_windows_sandbox::read_handle_loop;
use codex_windows_sandbox::spawn_process_with_pipes; use codex_windows_sandbox::spawn_process_with_pipes;
use codex_windows_sandbox::to_wide; use codex_windows_sandbox::to_wide;
use codex_windows_sandbox::PipeSpawnHandles;
use codex_windows_sandbox::SandboxPolicy;
use codex_windows_sandbox::StderrMode;
use codex_windows_sandbox::StdinMode;
use std::ffi::c_void; use std::ffi::c_void;
use std::fs::File; use std::fs::File;
use std::os::windows::io::FromRawHandle; use std::os::windows::io::FromRawHandle;
@@ -46,9 +47,9 @@ use std::sync::Arc;
use std::sync::Mutex as StdMutex; use std::sync::Mutex as StdMutex;
use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Foundation::HLOCAL; use windows_sys::Win32::Foundation::HLOCAL;
use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::Storage::FileSystem::CreateFileW; use windows_sys::Win32::Storage::FileSystem::CreateFileW;
use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_READ; use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_READ;
use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_WRITE; use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_WRITE;
@@ -56,16 +57,16 @@ use windows_sys::Win32::Storage::FileSystem::OPEN_EXISTING;
use windows_sys::Win32::System::Console::ClosePseudoConsole; use windows_sys::Win32::System::Console::ClosePseudoConsole;
use windows_sys::Win32::System::JobObjects::AssignProcessToJobObject; use windows_sys::Win32::System::JobObjects::AssignProcessToJobObject;
use windows_sys::Win32::System::JobObjects::CreateJobObjectW; use windows_sys::Win32::System::JobObjects::CreateJobObjectW;
use windows_sys::Win32::System::JobObjects::JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
use windows_sys::Win32::System::JobObjects::JOBOBJECT_EXTENDED_LIMIT_INFORMATION;
use windows_sys::Win32::System::JobObjects::JobObjectExtendedLimitInformation; use windows_sys::Win32::System::JobObjects::JobObjectExtendedLimitInformation;
use windows_sys::Win32::System::JobObjects::SetInformationJobObject; use windows_sys::Win32::System::JobObjects::SetInformationJobObject;
use windows_sys::Win32::System::JobObjects::JOBOBJECT_EXTENDED_LIMIT_INFORMATION;
use windows_sys::Win32::System::JobObjects::JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
use windows_sys::Win32::System::Threading::GetExitCodeProcess; use windows_sys::Win32::System::Threading::GetExitCodeProcess;
use windows_sys::Win32::System::Threading::GetProcessId; use windows_sys::Win32::System::Threading::GetProcessId;
use windows_sys::Win32::System::Threading::TerminateProcess;
use windows_sys::Win32::System::Threading::WaitForSingleObject;
use windows_sys::Win32::System::Threading::INFINITE; use windows_sys::Win32::System::Threading::INFINITE;
use windows_sys::Win32::System::Threading::PROCESS_INFORMATION; use windows_sys::Win32::System::Threading::PROCESS_INFORMATION;
use windows_sys::Win32::System::Threading::TerminateProcess;
use windows_sys::Win32::System::Threading::WaitForSingleObject;
#[path = "cwd_junction.rs"] #[path = "cwd_junction.rs"]
mod cwd_junction; mod cwd_junction;
@@ -332,13 +333,13 @@ fn spawn_output_reader(
}, },
}, },
}; };
if let Ok(mut guard) = writer.lock() { if let Ok(mut guard) = writer.lock()
if let Err(err) = write_frame(&mut *guard, &msg) { && let Err(err) = write_frame(&mut *guard, &msg)
log_note( {
&format!("runner output write failed: {err}"), log_note(
log_dir.as_deref(), &format!("runner output write failed: {err}"),
); log_dir.as_deref(),
} );
} }
}) })
} }
@@ -382,11 +383,11 @@ fn spawn_input_loop(
} }
} }
Message::Terminate { .. } => { Message::Terminate { .. } => {
if let Ok(guard) = process_handle.lock() { if let Ok(guard) = process_handle.lock()
if let Some(handle) = guard.as_ref() { && let Some(handle) = guard.as_ref()
unsafe { {
let _ = TerminateProcess(*handle, 1); unsafe {
} let _ = TerminateProcess(*handle, 1);
} }
} }
} }
@@ -544,10 +545,10 @@ pub fn main() -> Result<()> {
}, },
}, },
}; };
if let Ok(mut guard) = pipe_write.lock() { if let Ok(mut guard) = pipe_write.lock()
if let Err(err) = write_frame(&mut *guard, &exit_msg) { && let Err(err) = write_frame(&mut *guard, &exit_msg)
log_note(&format!("runner exit write failed: {err}"), log_dir); {
} log_note(&format!("runner exit write failed: {err}"), log_dir);
} }
std::process::exit(exit_code); std::process::exit(exit_code);
@@ -8,8 +8,8 @@
//! through the elevated runner. //! through the elevated runner.
use anyhow::Result; use anyhow::Result;
use base64::engine::general_purpose::STANDARD;
use base64::Engine as _; use base64::Engine as _;
use base64::engine::general_purpose::STANDARD;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use std::collections::HashMap; use std::collections::HashMap;
@@ -16,37 +16,37 @@ pub struct ElevatedSandboxCaptureRequest<'a> {
mod windows_impl { mod windows_impl {
use super::ElevatedSandboxCaptureRequest; use super::ElevatedSandboxCaptureRequest;
use crate::acl::allow_null_device; use crate::acl::allow_null_device;
use crate::allow::compute_allow_paths;
use crate::allow::AllowDenyPaths; use crate::allow::AllowDenyPaths;
use crate::allow::compute_allow_paths;
use crate::cap::load_or_create_cap_sids; use crate::cap::load_or_create_cap_sids;
use crate::env::ensure_non_interactive_pager; use crate::env::ensure_non_interactive_pager;
use crate::env::inherit_path_env; use crate::env::inherit_path_env;
use crate::env::normalize_null_device_env; use crate::env::normalize_null_device_env;
use crate::helper_materialization::resolve_helper_for_launch;
use crate::helper_materialization::HelperExecutable; use crate::helper_materialization::HelperExecutable;
use crate::helper_materialization::resolve_helper_for_launch;
use crate::identity::require_logon_sandbox_creds; use crate::identity::require_logon_sandbox_creds;
use crate::ipc_framed::decode_bytes;
use crate::ipc_framed::read_frame;
use crate::ipc_framed::write_frame;
use crate::ipc_framed::FramedMessage; use crate::ipc_framed::FramedMessage;
use crate::ipc_framed::Message; use crate::ipc_framed::Message;
use crate::ipc_framed::OutputStream; use crate::ipc_framed::OutputStream;
use crate::ipc_framed::SpawnRequest; use crate::ipc_framed::SpawnRequest;
use crate::ipc_framed::decode_bytes;
use crate::ipc_framed::read_frame;
use crate::ipc_framed::write_frame;
use crate::logging::log_failure; use crate::logging::log_failure;
use crate::logging::log_note; use crate::logging::log_note;
use crate::logging::log_start; use crate::logging::log_start;
use crate::logging::log_success; use crate::logging::log_success;
use crate::policy::parse_policy;
use crate::policy::SandboxPolicy; use crate::policy::SandboxPolicy;
use crate::policy::parse_policy;
use crate::token::convert_string_sid_to_sid; use crate::token::convert_string_sid_to_sid;
use crate::winutil::quote_windows_arg; use crate::winutil::quote_windows_arg;
use crate::winutil::resolve_sid; use crate::winutil::resolve_sid;
use crate::winutil::string_from_sid_bytes; use crate::winutil::string_from_sid_bytes;
use crate::winutil::to_wide; use crate::winutil::to_wide;
use anyhow::Result; use anyhow::Result;
use rand::rngs::SmallRng;
use rand::Rng; use rand::Rng;
use rand::SeedableRng; use rand::SeedableRng;
use rand::rngs::SmallRng;
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::c_void; use std::ffi::c_void;
use std::fs::File; use std::fs::File;
@@ -84,16 +84,16 @@ mod windows_impl {
return Some(cur); return Some(cur);
} }
if marker.is_file() { if marker.is_file() {
if let Ok(txt) = std::fs::read_to_string(&marker) { if let Ok(txt) = std::fs::read_to_string(&marker)
if let Some(rest) = txt.trim().strip_prefix("gitdir:") { && let Some(rest) = txt.trim().strip_prefix("gitdir:")
let gitdir = rest.trim(); {
let resolved = if Path::new(gitdir).is_absolute() { let gitdir = rest.trim();
PathBuf::from(gitdir) let resolved = if Path::new(gitdir).is_absolute() {
} else { PathBuf::from(gitdir)
cur.join(gitdir) } else {
}; cur.join(gitdir)
return resolved.parent().map(|p| p.to_path_buf()).or(Some(cur)); };
} return resolved.parent().map(|p| p.to_path_buf()).or(Some(cur));
} }
return Some(cur); return Some(cur);
} }
@@ -143,7 +143,11 @@ mod windows_impl {
/// Generates a unique named-pipe path used to communicate with the runner process. /// Generates a unique named-pipe path used to communicate with the runner process.
fn pipe_name(suffix: &str) -> String { fn pipe_name(suffix: &str) -> String {
let mut rng = SmallRng::from_entropy(); let mut rng = SmallRng::from_entropy();
format!(r"\\.\pipe\codex-runner-{:x}-{}", rng.gen::<u128>(), suffix) format!(
r"\\.\pipe\codex-runner-{:x}-{}",
rng.r#gen::<u128>(),
suffix
)
} }
/// Creates a named pipe whose DACL only allows the sandbox user to connect. /// Creates a named pipe whose DACL only allows the sandbox user to connect.
@@ -507,8 +511,8 @@ pub use windows_impl::run_windows_sandbox_capture;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
mod stub { mod stub {
use super::ElevatedSandboxCaptureRequest; use super::ElevatedSandboxCaptureRequest;
use anyhow::bail;
use anyhow::Result; use anyhow::Result;
use anyhow::bail;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct CaptureResult { pub struct CaptureResult {
+8 -8
View File
@@ -30,15 +30,15 @@ pub fn ensure_non_interactive_pager(env_map: &mut HashMap<String, String>) {
// Keep PATH and PATHEXT stable for callers that rely on inheriting the parent process env. // Keep PATH and PATHEXT stable for callers that rely on inheriting the parent process env.
pub fn inherit_path_env(env_map: &mut HashMap<String, String>) { pub fn inherit_path_env(env_map: &mut HashMap<String, String>) {
if !env_map.contains_key("PATH") { if !env_map.contains_key("PATH")
if let Ok(path) = env::var("PATH") { && let Ok(path) = env::var("PATH")
env_map.insert("PATH".into(), path); {
} env_map.insert("PATH".into(), path);
} }
if !env_map.contains_key("PATHEXT") { if !env_map.contains_key("PATHEXT")
if let Ok(pathext) = env::var("PATHEXT") { && let Ok(pathext) = env::var("PATHEXT")
env_map.insert("PATHEXT".into(), pathext); {
} env_map.insert("PATHEXT".into(), pathext);
} }
} }
+7 -8
View File
@@ -4,25 +4,25 @@ use anyhow::Result;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use windows::core::Interface;
use windows::core::BSTR;
use windows::Win32::Foundation::VARIANT_TRUE; use windows::Win32::Foundation::VARIANT_TRUE;
use windows::Win32::NetworkManagement::WindowsFirewall::INetFwPolicy2; use windows::Win32::NetworkManagement::WindowsFirewall::INetFwPolicy2;
use windows::Win32::NetworkManagement::WindowsFirewall::INetFwRule3; use windows::Win32::NetworkManagement::WindowsFirewall::INetFwRule3;
use windows::Win32::NetworkManagement::WindowsFirewall::INetFwRules; use windows::Win32::NetworkManagement::WindowsFirewall::INetFwRules;
use windows::Win32::NetworkManagement::WindowsFirewall::NetFwPolicy2;
use windows::Win32::NetworkManagement::WindowsFirewall::NetFwRule;
use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_ACTION_BLOCK; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_ACTION_BLOCK;
use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_ANY; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_ANY;
use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_TCP; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_TCP;
use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_UDP; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_UDP;
use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_PROFILE2_ALL; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_PROFILE2_ALL;
use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_RULE_DIR_OUT; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_RULE_DIR_OUT;
use windows::Win32::NetworkManagement::WindowsFirewall::NetFwPolicy2;
use windows::Win32::NetworkManagement::WindowsFirewall::NetFwRule;
use windows::Win32::System::Com::CLSCTX_INPROC_SERVER;
use windows::Win32::System::Com::COINIT_APARTMENTTHREADED;
use windows::Win32::System::Com::CoCreateInstance; use windows::Win32::System::Com::CoCreateInstance;
use windows::Win32::System::Com::CoInitializeEx; use windows::Win32::System::Com::CoInitializeEx;
use windows::Win32::System::Com::CoUninitialize; use windows::Win32::System::Com::CoUninitialize;
use windows::Win32::System::Com::CLSCTX_INPROC_SERVER; use windows::core::BSTR;
use windows::Win32::System::Com::COINIT_APARTMENTTHREADED; use windows::core::Interface;
use codex_windows_sandbox::SetupErrorCode; use codex_windows_sandbox::SetupErrorCode;
use codex_windows_sandbox::SetupFailure; use codex_windows_sandbox::SetupFailure;
@@ -40,8 +40,7 @@ const OFFLINE_BLOCK_LOOPBACK_TCP_RULE_FRIENDLY: &str =
const OFFLINE_BLOCK_LOOPBACK_UDP_RULE_FRIENDLY: &str = "Codex Sandbox Offline - Block Loopback UDP"; const OFFLINE_BLOCK_LOOPBACK_UDP_RULE_FRIENDLY: &str = "Codex Sandbox Offline - Block Loopback UDP";
const OFFLINE_PROXY_ALLOW_RULE_NAME: &str = "codex_sandbox_offline_allow_loopback_proxy"; const OFFLINE_PROXY_ALLOW_RULE_NAME: &str = "codex_sandbox_offline_allow_loopback_proxy";
const LOOPBACK_REMOTE_ADDRESSES: &str = "127.0.0.0/8,::1"; const LOOPBACK_REMOTE_ADDRESSES: &str = "127.0.0.0/8,::1";
const NON_LOOPBACK_REMOTE_ADDRESSES: &str = const NON_LOOPBACK_REMOTE_ADDRESSES: &str = "0.0.0.0-126.255.255.255,128.0.0.0-255.255.255.255,::,::2-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
"0.0.0.0-126.255.255.255,128.0.0.0-255.255.255.255,::,::2-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
struct BlockRuleSpec<'a> { struct BlockRuleSpec<'a> {
internal_name: &'a str, internal_name: &'a str,
@@ -45,12 +45,12 @@ pub(crate) fn helper_bin_dir(codex_home: &Path) -> PathBuf {
} }
pub(crate) fn legacy_lookup(kind: HelperExecutable) -> PathBuf { pub(crate) fn legacy_lookup(kind: HelperExecutable) -> PathBuf {
if let Ok(exe) = std::env::current_exe() { if let Ok(exe) = std::env::current_exe()
if let Some(dir) = exe.parent() { && let Some(dir) = exe.parent()
let candidate = dir.join(kind.file_name()); {
if candidate.exists() { let candidate = dir.join(kind.file_name());
return candidate; if candidate.exists() {
} return candidate;
} }
} }
PathBuf::from(kind.file_name()) PathBuf::from(kind.file_name())
@@ -377,4 +377,3 @@ mod tests {
); );
} }
} }
+51 -46
View File
@@ -1,3 +1,7 @@
// Rust 2024 surfaces this lint across the crate; keep the edition bump separate
// from the eventual unsafe cleanup.
#![allow(unsafe_op_in_unsafe_fn)]
macro_rules! windows_modules { macro_rules! windows_modules {
($($name:ident),+ $(,)?) => { ($($name:ident),+ $(,)?) => {
$(#[cfg(target_os = "windows")] mod $name;)+ $(#[cfg(target_os = "windows")] mod $name;)+
@@ -70,10 +74,10 @@ pub use dpapi::protect as dpapi_protect;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use dpapi::unprotect as dpapi_unprotect; pub use dpapi::unprotect as dpapi_unprotect;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use elevated_impl::run_windows_sandbox_capture as run_windows_sandbox_capture_elevated;
#[cfg(target_os = "windows")]
pub use elevated_impl::ElevatedSandboxCaptureRequest; pub use elevated_impl::ElevatedSandboxCaptureRequest;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use elevated_impl::run_windows_sandbox_capture as run_windows_sandbox_capture_elevated;
#[cfg(target_os = "windows")]
pub use helper_materialization::resolve_current_exe_for_launch; pub use helper_materialization::resolve_current_exe_for_launch;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use hide_users::hide_current_user_profile_dir; pub use hide_users::hide_current_user_profile_dir;
@@ -84,15 +88,21 @@ pub use identity::require_logon_sandbox_creds;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use identity::sandbox_setup_is_complete; pub use identity::sandbox_setup_is_complete;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use logging::log_note;
#[cfg(target_os = "windows")]
pub use logging::LOG_FILE_NAME; pub use logging::LOG_FILE_NAME;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use logging::log_note;
#[cfg(target_os = "windows")]
pub use path_normalization::canonicalize_path; pub use path_normalization::canonicalize_path;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use policy::SandboxPolicy;
#[cfg(target_os = "windows")]
pub use policy::parse_policy; pub use policy::parse_policy;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use policy::SandboxPolicy; pub use process::PipeSpawnHandles;
#[cfg(target_os = "windows")]
pub use process::StderrMode;
#[cfg(target_os = "windows")]
pub use process::StdinMode;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use process::create_process_as_user; pub use process::create_process_as_user;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@@ -100,11 +110,11 @@ 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 process::PipeSpawnHandles; pub use setup::SETUP_VERSION;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use process::StderrMode; pub use setup::SandboxSetupRequest;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use process::StdinMode; pub use setup::SetupRootOverrides;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use setup::run_elevated_setup; pub use setup::run_elevated_setup;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@@ -118,11 +128,11 @@ pub use setup::sandbox_dir;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use setup::sandbox_secrets_dir; pub use setup::sandbox_secrets_dir;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use setup::SandboxSetupRequest; pub use setup_error::SetupErrorCode;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use setup::SetupRootOverrides; pub use setup_error::SetupErrorReport;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use setup::SETUP_VERSION; pub use setup_error::SetupFailure;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use setup_error::extract_failure as extract_setup_failure; pub use setup_error::extract_failure as extract_setup_failure;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@@ -132,12 +142,6 @@ pub use setup_error::setup_error_path;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use setup_error::write_setup_error_report; pub use setup_error::write_setup_error_report;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use setup_error::SetupErrorCode;
#[cfg(target_os = "windows")]
pub use setup_error::SetupErrorReport;
#[cfg(target_os = "windows")]
pub use setup_error::SetupFailure;
#[cfg(target_os = "windows")]
pub use token::convert_string_sid_to_sid; pub use token::convert_string_sid_to_sid;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use token::create_readonly_token_with_cap_from; pub use token::create_readonly_token_with_cap_from;
@@ -148,14 +152,14 @@ pub use token::create_workspace_write_token_with_caps_from;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use token::get_current_token_for_restriction; pub use token::get_current_token_for_restriction;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use windows_impl::CaptureResult;
#[cfg(target_os = "windows")]
pub use windows_impl::run_windows_sandbox_capture; pub use windows_impl::run_windows_sandbox_capture;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use windows_impl::run_windows_sandbox_capture_with_extra_deny_write_paths; pub use windows_impl::run_windows_sandbox_capture_with_extra_deny_write_paths;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use windows_impl::run_windows_sandbox_legacy_preflight; pub use windows_impl::run_windows_sandbox_legacy_preflight;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use windows_impl::CaptureResult;
#[cfg(target_os = "windows")]
pub use winutil::quote_windows_arg; pub use winutil::quote_windows_arg;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use winutil::string_from_sid_bytes; pub use winutil::string_from_sid_bytes;
@@ -168,14 +172,14 @@ pub use workspace_acl::protect_workspace_agents_dir;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use workspace_acl::protect_workspace_codex_dir; pub use workspace_acl::protect_workspace_codex_dir;
#[cfg(not(target_os = "windows"))]
pub use stub::CaptureResult;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
pub use stub::apply_world_writable_scan_and_denies; pub use stub::apply_world_writable_scan_and_denies;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
pub use stub::run_windows_sandbox_capture; pub use stub::run_windows_sandbox_capture;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
pub use stub::run_windows_sandbox_legacy_preflight; pub use stub::run_windows_sandbox_legacy_preflight;
#[cfg(not(target_os = "windows"))]
pub use stub::CaptureResult;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
mod windows_impl { mod windows_impl {
@@ -183,8 +187,8 @@ mod windows_impl {
use super::acl::add_deny_write_ace; use super::acl::add_deny_write_ace;
use super::acl::allow_null_device; use super::acl::allow_null_device;
use super::acl::revoke_ace; use super::acl::revoke_ace;
use super::allow::compute_allow_paths;
use super::allow::AllowDenyPaths; use super::allow::AllowDenyPaths;
use super::allow::compute_allow_paths;
use super::cap::load_or_create_cap_sids; use super::cap::load_or_create_cap_sids;
use super::cap::workspace_cap_sid_for_cwd; use super::cap::workspace_cap_sid_for_cwd;
use super::env::apply_no_network_to_env; use super::env::apply_no_network_to_env;
@@ -194,8 +198,8 @@ mod windows_impl {
use super::logging::log_start; use super::logging::log_start;
use super::logging::log_success; use super::logging::log_success;
use super::path_normalization::canonicalize_path; use super::path_normalization::canonicalize_path;
use super::policy::parse_policy;
use super::policy::SandboxPolicy; use super::policy::SandboxPolicy;
use super::policy::parse_policy;
use super::process::create_process_as_user; use super::process::create_process_as_user;
use super::token::convert_string_sid_to_sid; use super::token::convert_string_sid_to_sid;
use super::token::create_workspace_write_token_with_caps_from; use super::token::create_workspace_write_token_with_caps_from;
@@ -211,13 +215,13 @@ mod windows_impl {
use std::ptr; use std::ptr;
use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::SetHandleInformation;
use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Foundation::HANDLE_FLAG_INHERIT; use windows_sys::Win32::Foundation::HANDLE_FLAG_INHERIT;
use windows_sys::Win32::Foundation::SetHandleInformation;
use windows_sys::Win32::System::Pipes::CreatePipe; use windows_sys::Win32::System::Pipes::CreatePipe;
use windows_sys::Win32::System::Threading::GetExitCodeProcess; use windows_sys::Win32::System::Threading::GetExitCodeProcess;
use windows_sys::Win32::System::Threading::WaitForSingleObject;
use windows_sys::Win32::System::Threading::INFINITE; use windows_sys::Win32::System::Threading::INFINITE;
use windows_sys::Win32::System::Threading::WaitForSingleObject;
type PipeHandles = ((HANDLE, HANDLE), (HANDLE, HANDLE), (HANDLE, HANDLE)); type PipeHandles = ((HANDLE, HANDLE), (HANDLE, HANDLE), (HANDLE, HANDLE));
@@ -355,15 +359,15 @@ mod windows_impl {
}; };
unsafe { unsafe {
if is_workspace_write { if is_workspace_write
if let Ok(base) = super::token::get_current_token_for_restriction() { && let Ok(base) = super::token::get_current_token_for_restriction()
if let Ok(bytes) = super::token::get_logon_sid_bytes(base) { {
let mut tmp = bytes.clone(); if let Ok(bytes) = super::token::get_logon_sid_bytes(base) {
let psid2 = tmp.as_mut_ptr() as *mut c_void; let mut tmp = bytes.clone();
allow_null_device(psid2); let psid2 = tmp.as_mut_ptr() as *mut c_void;
} allow_null_device(psid2);
windows_sys::Win32::Foundation::CloseHandle(base);
} }
windows_sys::Win32::Foundation::CloseHandle(base);
} }
} }
@@ -384,23 +388,24 @@ mod windows_impl {
} else { } else {
psid_generic psid_generic
}; };
if let Ok(added) = add_allow_ace(p, psid) { if let Ok(added) = add_allow_ace(p, psid)
if added { && added
if persist_aces { {
if p.is_dir() { if persist_aces {
// best-effort seeding omitted intentionally if p.is_dir() {
} // best-effort seeding omitted intentionally
} else {
guards.push((p.clone(), psid));
} }
} else {
guards.push((p.clone(), psid));
} }
} }
} }
for p in &deny { for p in &deny {
if let Ok(added) = add_deny_write_ace(p, psid_generic) { if let Ok(added) = add_deny_write_ace(p, psid_generic)
if added && !persist_aces { && added
guards.push((p.clone(), psid_generic)); && !persist_aces
} {
guards.push((p.clone(), psid_generic));
} }
} }
allow_null_device(psid_generic); allow_null_device(psid_generic);
@@ -631,8 +636,8 @@ mod windows_impl {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
mod stub { mod stub {
use anyhow::bail;
use anyhow::Result; use anyhow::Result;
use anyhow::bail;
use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::SandboxPolicy;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::Path; use std::path::Path;
+5 -6
View File
@@ -37,12 +37,11 @@ fn log_file_path(base_dir: &Path) -> Option<PathBuf> {
} }
fn append_line(line: &str, base_dir: Option<&Path>) { fn append_line(line: &str, base_dir: Option<&Path>) {
if let Some(dir) = base_dir { if let Some(dir) = base_dir
if let Some(path) = log_file_path(dir) { && let Some(path) = log_file_path(dir)
if let Ok(mut f) = OpenOptions::new().create(true).append(true).open(path) { && let Ok(mut f) = OpenOptions::new().create(true).append(true).open(path)
let _ = writeln!(f, "{}", line); {
} let _ = writeln!(f, "{line}");
}
} }
} }
@@ -1,14 +1,14 @@
use anyhow::Result; use anyhow::Result;
use std::ffi::OsStr; use std::ffi::OsStr;
use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::ERROR_ALREADY_EXISTS; use windows_sys::Win32::Foundation::ERROR_ALREADY_EXISTS;
use windows_sys::Win32::Foundation::ERROR_FILE_NOT_FOUND; use windows_sys::Win32::Foundation::ERROR_FILE_NOT_FOUND;
use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Threading::CreateMutexW; use windows_sys::Win32::System::Threading::CreateMutexW;
use windows_sys::Win32::System::Threading::MUTEX_ALL_ACCESS;
use windows_sys::Win32::System::Threading::OpenMutexW; use windows_sys::Win32::System::Threading::OpenMutexW;
use windows_sys::Win32::System::Threading::ReleaseMutex; use windows_sys::Win32::System::Threading::ReleaseMutex;
use windows_sys::Win32::System::Threading::MUTEX_ALL_ACCESS;
use super::to_wide; use super::to_wide;
@@ -1,27 +1,27 @@
#![cfg(target_os = "windows")] #![cfg(target_os = "windows")]
use anyhow::Result; use anyhow::Result;
use base64::engine::general_purpose::STANDARD as BASE64;
use base64::Engine; use base64::Engine;
use rand::rngs::SmallRng; use base64::engine::general_purpose::STANDARD as BASE64;
use rand::RngCore; use rand::RngCore;
use rand::SeedableRng; use rand::SeedableRng;
use rand::rngs::SmallRng;
use serde::Serialize; use serde::Serialize;
use std::ffi::c_void;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::ffi::c_void;
use std::fs::File; use std::fs::File;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use windows_sys::Win32::Foundation::ERROR_INSUFFICIENT_BUFFER;
use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::LocalFree; use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::Foundation::ERROR_INSUFFICIENT_BUFFER; use windows_sys::Win32::NetworkManagement::NetManagement::LOCALGROUP_INFO_1;
use windows_sys::Win32::NetworkManagement::NetManagement::LOCALGROUP_MEMBERS_INFO_3;
use windows_sys::Win32::NetworkManagement::NetManagement::NERR_Success; use windows_sys::Win32::NetworkManagement::NetManagement::NERR_Success;
use windows_sys::Win32::NetworkManagement::NetManagement::NetLocalGroupAdd; use windows_sys::Win32::NetworkManagement::NetManagement::NetLocalGroupAdd;
use windows_sys::Win32::NetworkManagement::NetManagement::NetLocalGroupAddMembers; use windows_sys::Win32::NetworkManagement::NetManagement::NetLocalGroupAddMembers;
use windows_sys::Win32::NetworkManagement::NetManagement::NetUserAdd; use windows_sys::Win32::NetworkManagement::NetManagement::NetUserAdd;
use windows_sys::Win32::NetworkManagement::NetManagement::NetUserSetInfo; use windows_sys::Win32::NetworkManagement::NetManagement::NetUserSetInfo;
use windows_sys::Win32::NetworkManagement::NetManagement::LOCALGROUP_INFO_1;
use windows_sys::Win32::NetworkManagement::NetManagement::LOCALGROUP_MEMBERS_INFO_3;
use windows_sys::Win32::NetworkManagement::NetManagement::UF_DONT_EXPIRE_PASSWD; use windows_sys::Win32::NetworkManagement::NetManagement::UF_DONT_EXPIRE_PASSWD;
use windows_sys::Win32::NetworkManagement::NetManagement::UF_SCRIPT; use windows_sys::Win32::NetworkManagement::NetManagement::UF_SCRIPT;
use windows_sys::Win32::NetworkManagement::NetManagement::USER_INFO_1; use windows_sys::Win32::NetworkManagement::NetManagement::USER_INFO_1;
@@ -34,14 +34,14 @@ use windows_sys::Win32::Security::LookupAccountNameW;
use windows_sys::Win32::Security::LookupAccountSidW; use windows_sys::Win32::Security::LookupAccountSidW;
use windows_sys::Win32::Security::SID_NAME_USE; use windows_sys::Win32::Security::SID_NAME_USE;
use codex_windows_sandbox::SETUP_VERSION;
use codex_windows_sandbox::SetupErrorCode;
use codex_windows_sandbox::SetupFailure;
use codex_windows_sandbox::dpapi_protect; use codex_windows_sandbox::dpapi_protect;
use codex_windows_sandbox::sandbox_dir; use codex_windows_sandbox::sandbox_dir;
use codex_windows_sandbox::sandbox_secrets_dir; use codex_windows_sandbox::sandbox_secrets_dir;
use codex_windows_sandbox::string_from_sid_bytes; use codex_windows_sandbox::string_from_sid_bytes;
use codex_windows_sandbox::to_wide; use codex_windows_sandbox::to_wide;
use codex_windows_sandbox::SetupErrorCode;
use codex_windows_sandbox::SetupFailure;
use codex_windows_sandbox::SETUP_VERSION;
pub const SANDBOX_USERS_GROUP: &str = "CodexSandboxUsers"; pub const SANDBOX_USERS_GROUP: &str = "CodexSandboxUsers";
const SANDBOX_USERS_GROUP_COMMENT: &str = "Codex sandbox internal group (managed)"; const SANDBOX_USERS_GROUP_COMMENT: &str = "Codex sandbox internal group (managed)";
@@ -189,15 +189,16 @@ pub fn sanitize_setup_metric_tag_value(value: &str) -> String {
fn redact_home_paths(value: &str) -> String { fn redact_home_paths(value: &str) -> String {
let mut usernames: Vec<String> = Vec::new(); let mut usernames: Vec<String> = Vec::new();
if let Ok(username) = std::env::var("USERNAME") { if let Ok(username) = std::env::var("USERNAME")
if !username.trim().is_empty() { && !username.trim().is_empty()
usernames.push(username); {
} usernames.push(username);
} }
if let Ok(user) = std::env::var("USER") { if let Ok(user) = std::env::var("USER")
if !user.trim().is_empty() && !usernames.iter().any(|v| v.eq_ignore_ascii_case(&user)) { && !user.trim().is_empty()
usernames.push(user); && !usernames.iter().any(|v| v.eq_ignore_ascii_case(&user))
} {
usernames.push(user);
} }
redact_username_segments(value, &usernames) redact_username_segments(value, &usernames)
@@ -4,8 +4,13 @@ mod firewall;
use anyhow::Context; use anyhow::Context;
use anyhow::Result; use anyhow::Result;
use base64::engine::general_purpose::STANDARD as BASE64;
use base64::Engine; use base64::Engine;
use base64::engine::general_purpose::STANDARD as BASE64;
use codex_windows_sandbox::LOG_FILE_NAME;
use codex_windows_sandbox::SETUP_VERSION;
use codex_windows_sandbox::SetupErrorCode;
use codex_windows_sandbox::SetupErrorReport;
use codex_windows_sandbox::SetupFailure;
use codex_windows_sandbox::canonicalize_path; use codex_windows_sandbox::canonicalize_path;
use codex_windows_sandbox::convert_string_sid_to_sid; use codex_windows_sandbox::convert_string_sid_to_sid;
use codex_windows_sandbox::ensure_allow_mask_aces_with_inheritance; use codex_windows_sandbox::ensure_allow_mask_aces_with_inheritance;
@@ -25,16 +30,11 @@ use codex_windows_sandbox::string_from_sid_bytes;
use codex_windows_sandbox::to_wide; use codex_windows_sandbox::to_wide;
use codex_windows_sandbox::workspace_cap_sid_for_cwd; use codex_windows_sandbox::workspace_cap_sid_for_cwd;
use codex_windows_sandbox::write_setup_error_report; use codex_windows_sandbox::write_setup_error_report;
use codex_windows_sandbox::SetupErrorCode;
use codex_windows_sandbox::SetupErrorReport;
use codex_windows_sandbox::SetupFailure;
use codex_windows_sandbox::LOG_FILE_NAME;
use codex_windows_sandbox::SETUP_VERSION;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use std::collections::HashSet; use std::collections::HashSet;
use std::ffi::c_void;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::ffi::c_void;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use std::os::windows::process::CommandExt; use std::os::windows::process::CommandExt;
@@ -44,17 +44,17 @@ use std::process::Command;
use std::process::Stdio; use std::process::Stdio;
use std::sync::mpsc; use std::sync::mpsc;
use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::Foundation::HLOCAL; use windows_sys::Win32::Foundation::HLOCAL;
use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::Security::ACL;
use windows_sys::Win32::Security::Authorization::ConvertStringSidToSidW; use windows_sys::Win32::Security::Authorization::ConvertStringSidToSidW;
use windows_sys::Win32::Security::Authorization::SetEntriesInAclW;
use windows_sys::Win32::Security::Authorization::SetNamedSecurityInfoW;
use windows_sys::Win32::Security::Authorization::EXPLICIT_ACCESS_W; use windows_sys::Win32::Security::Authorization::EXPLICIT_ACCESS_W;
use windows_sys::Win32::Security::Authorization::GRANT_ACCESS; use windows_sys::Win32::Security::Authorization::GRANT_ACCESS;
use windows_sys::Win32::Security::Authorization::SE_FILE_OBJECT; use windows_sys::Win32::Security::Authorization::SE_FILE_OBJECT;
use windows_sys::Win32::Security::Authorization::SetEntriesInAclW;
use windows_sys::Win32::Security::Authorization::SetNamedSecurityInfoW;
use windows_sys::Win32::Security::Authorization::TRUSTEE_IS_SID; use windows_sys::Win32::Security::Authorization::TRUSTEE_IS_SID;
use windows_sys::Win32::Security::Authorization::TRUSTEE_W; use windows_sys::Win32::Security::Authorization::TRUSTEE_W;
use windows_sys::Win32::Security::ACL;
use windows_sys::Win32::Security::CONTAINER_INHERIT_ACE; use windows_sys::Win32::Security::CONTAINER_INHERIT_ACE;
use windows_sys::Win32::Security::DACL_SECURITY_INFORMATION; use windows_sys::Win32::Security::DACL_SECURITY_INFORMATION;
use windows_sys::Win32::Security::OBJECT_INHERIT_ACE; use windows_sys::Win32::Security::OBJECT_INHERIT_ACE;
@@ -10,22 +10,22 @@ use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::process::Stdio; use std::process::Stdio;
use crate::allow::compute_allow_paths;
use crate::allow::AllowDenyPaths; use crate::allow::AllowDenyPaths;
use crate::allow::compute_allow_paths;
use crate::helper_materialization::helper_bin_dir; use crate::helper_materialization::helper_bin_dir;
use crate::logging::log_note; use crate::logging::log_note;
use crate::path_normalization::canonical_path_key; use crate::path_normalization::canonical_path_key;
use crate::policy::SandboxPolicy; use crate::policy::SandboxPolicy;
use crate::setup_error::SetupErrorCode;
use crate::setup_error::SetupFailure;
use crate::setup_error::clear_setup_error_report; use crate::setup_error::clear_setup_error_report;
use crate::setup_error::failure; use crate::setup_error::failure;
use crate::setup_error::read_setup_error_report; use crate::setup_error::read_setup_error_report;
use crate::setup_error::SetupErrorCode;
use crate::setup_error::SetupFailure;
use anyhow::anyhow;
use anyhow::Context; use anyhow::Context;
use anyhow::Result; use anyhow::Result;
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use anyhow::anyhow;
use base64::Engine; use base64::Engine;
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::GetLastError;
@@ -332,10 +332,10 @@ fn profile_read_roots(user_profile: &Path) -> Vec<PathBuf> {
fn gather_helper_read_roots(codex_home: &Path) -> Vec<PathBuf> { fn gather_helper_read_roots(codex_home: &Path) -> Vec<PathBuf> {
let mut roots = Vec::new(); let mut roots = Vec::new();
if let Ok(exe) = std::env::current_exe() { if let Ok(exe) = std::env::current_exe()
if let Some(dir) = exe.parent() { && let Some(dir) = exe.parent()
roots.push(dir.to_path_buf()); {
} roots.push(dir.to_path_buf());
} }
let helper_dir = helper_bin_dir(codex_home); let helper_dir = helper_bin_dir(codex_home);
let _ = std::fs::create_dir_all(&helper_dir); let _ = std::fs::create_dir_all(&helper_dir);
@@ -503,10 +503,10 @@ pub(crate) fn offline_proxy_settings_from_env(
pub(crate) fn proxy_ports_from_env(env_map: &HashMap<String, String>) -> Vec<u16> { pub(crate) fn proxy_ports_from_env(env_map: &HashMap<String, String>) -> Vec<u16> {
let mut ports = BTreeSet::new(); let mut ports = BTreeSet::new();
for key in PROXY_ENV_KEYS { for key in PROXY_ENV_KEYS {
if let Some(value) = env_map.get(*key) { if let Some(value) = env_map.get(*key)
if let Some(port) = loopback_proxy_port_from_url(value) { && let Some(port) = loopback_proxy_port_from_url(value)
ports.insert(port); {
} ports.insert(port);
} }
} }
ports.into_iter().collect() ports.into_iter().collect()
@@ -570,12 +570,12 @@ fn quote_arg(arg: &str) -> String {
} }
fn find_setup_exe() -> PathBuf { fn find_setup_exe() -> PathBuf {
if let Ok(exe) = std::env::current_exe() { if let Ok(exe) = std::env::current_exe()
if let Some(dir) = exe.parent() { && let Some(dir) = exe.parent()
let candidate = dir.join("codex-windows-sandbox-setup.exe"); {
if candidate.exists() { let candidate = dir.join("codex-windows-sandbox-setup.exe");
return candidate; if candidate.exists() {
} return candidate;
} }
} }
PathBuf::from("codex-windows-sandbox-setup.exe") PathBuf::from("codex-windows-sandbox-setup.exe")
@@ -606,11 +606,11 @@ fn run_setup_exe(
codex_home: &Path, codex_home: &Path,
) -> Result<()> { ) -> Result<()> {
use windows_sys::Win32::System::Threading::GetExitCodeProcess; use windows_sys::Win32::System::Threading::GetExitCodeProcess;
use windows_sys::Win32::System::Threading::WaitForSingleObject;
use windows_sys::Win32::System::Threading::INFINITE; use windows_sys::Win32::System::Threading::INFINITE;
use windows_sys::Win32::UI::Shell::ShellExecuteExW; use windows_sys::Win32::System::Threading::WaitForSingleObject;
use windows_sys::Win32::UI::Shell::SEE_MASK_NOCLOSEPROCESS; use windows_sys::Win32::UI::Shell::SEE_MASK_NOCLOSEPROCESS;
use windows_sys::Win32::UI::Shell::SHELLEXECUTEINFOW; use windows_sys::Win32::UI::Shell::SHELLEXECUTEINFOW;
use windows_sys::Win32::UI::Shell::ShellExecuteExW;
let exe = find_setup_exe(); let exe = find_setup_exe();
let payload_json = serde_json::to_string(payload).map_err(|err| { let payload_json = serde_json::to_string(payload).map_err(|err| {
failure( failure(
@@ -801,13 +801,13 @@ fn filter_sensitive_write_roots(mut roots: Vec<PathBuf>, codex_home: &Path) -> V
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::WINDOWS_PLATFORM_DEFAULT_READ_ROOTS;
use super::gather_legacy_full_read_roots; use super::gather_legacy_full_read_roots;
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;
use super::profile_read_roots; use super::profile_read_roots;
use super::proxy_ports_from_env; use super::proxy_ports_from_env;
use super::WINDOWS_PLATFORM_DEFAULT_READ_ROOTS;
use crate::helper_materialization::helper_bin_dir; use crate::helper_materialization::helper_bin_dir;
use crate::policy::SandboxPolicy; use crate::policy::SandboxPolicy;
use codex_protocol::protocol::ReadOnlyAccess; use codex_protocol::protocol::ReadOnlyAccess;
@@ -1020,8 +1020,10 @@ mod tests {
let policy = SandboxPolicy::ReadOnly { let policy = SandboxPolicy::ReadOnly {
access: ReadOnlyAccess::Restricted { access: ReadOnlyAccess::Restricted {
include_platform_defaults: false, include_platform_defaults: false,
readable_roots: vec![AbsolutePathBuf::from_absolute_path(&readable_root) readable_roots: vec![
.expect("absolute readable root")], AbsolutePathBuf::from_absolute_path(&readable_root)
.expect("absolute readable root"),
],
}, },
network_access: false, network_access: false,
}; };
@@ -1036,9 +1038,11 @@ mod tests {
assert!(roots.contains(&expected_helper)); assert!(roots.contains(&expected_helper));
assert!(roots.contains(&expected_cwd)); assert!(roots.contains(&expected_cwd));
assert!(roots.contains(&expected_readable)); assert!(roots.contains(&expected_readable));
assert!(canonical_windows_platform_default_roots() assert!(
.into_iter() canonical_windows_platform_default_roots()
.all(|path| !roots.contains(&path))); .into_iter()
.all(|path| !roots.contains(&path))
);
} }
#[test] #[test]
@@ -1057,9 +1061,11 @@ mod tests {
let roots = gather_read_roots(&command_cwd, &policy, &codex_home); let roots = gather_read_roots(&command_cwd, &policy, &codex_home);
assert!(canonical_windows_platform_default_roots() assert!(
.into_iter() canonical_windows_platform_default_roots()
.all(|path| roots.contains(&path))); .into_iter()
.all(|path| roots.contains(&path))
);
} }
#[test] #[test]
@@ -1071,8 +1077,10 @@ mod tests {
fs::create_dir_all(&command_cwd).expect("create workspace"); fs::create_dir_all(&command_cwd).expect("create workspace");
fs::create_dir_all(&writable_root).expect("create writable root"); fs::create_dir_all(&writable_root).expect("create writable root");
let policy = SandboxPolicy::WorkspaceWrite { let policy = SandboxPolicy::WorkspaceWrite {
writable_roots: vec![AbsolutePathBuf::from_absolute_path(&writable_root) writable_roots: vec![
.expect("absolute writable root")], AbsolutePathBuf::from_absolute_path(&writable_root)
.expect("absolute writable root"),
],
read_only_access: ReadOnlyAccess::Restricted { read_only_access: ReadOnlyAccess::Restricted {
include_platform_defaults: false, include_platform_defaults: false,
readable_roots: Vec::new(), readable_roots: Vec::new(),
@@ -1099,8 +1107,10 @@ mod tests {
let roots = gather_legacy_full_read_roots(&command_cwd, &policy, &codex_home); let roots = gather_legacy_full_read_roots(&command_cwd, &policy, &codex_home);
assert!(canonical_windows_platform_default_roots() assert!(
.into_iter() canonical_windows_platform_default_roots()
.all(|path| roots.contains(&path))); .into_iter()
.all(|path| roots.contains(&path))
);
} }
} }
+2 -2
View File
@@ -130,7 +130,7 @@ pub unsafe fn world_sid() -> Result<Vec<u8>> {
/// Caller is responsible for freeing the returned SID with `LocalFree`. /// Caller is responsible for freeing the returned SID with `LocalFree`.
pub unsafe fn convert_string_sid_to_sid(s: &str) -> Option<*mut c_void> { pub unsafe fn convert_string_sid_to_sid(s: &str) -> Option<*mut c_void> {
#[link(name = "advapi32")] #[link(name = "advapi32")]
extern "system" { unsafe extern "system" {
fn ConvertStringSidToSidW(StringSid: *const u16, Sid: *mut *mut c_void) -> i32; fn ConvertStringSidToSidW(StringSid: *const u16, Sid: *mut *mut c_void) -> i32;
} }
let mut psid: *mut c_void = std::ptr::null_mut(); let mut psid: *mut c_void = std::ptr::null_mut();
@@ -153,7 +153,7 @@ pub unsafe fn get_current_token_for_restriction() -> Result<HANDLE> {
| TOKEN_ADJUST_PRIVILEGES; | TOKEN_ADJUST_PRIVILEGES;
let mut h: HANDLE = 0; let mut h: HANDLE = 0;
#[link(name = "advapi32")] #[link(name = "advapi32")]
extern "system" { unsafe extern "system" {
fn OpenProcessToken( fn OpenProcessToken(
ProcessHandle: HANDLE, ProcessHandle: HANDLE,
DesiredAccess: u32, DesiredAccess: u32,