Codex Handbook
windows-sandbox-rs/src/unified_exec/backends/elevated.rs 196 lines
use super::windows_common::finish_driver_spawn;use super::windows_common::make_runner_resizer;use super::windows_common::start_runner_pipe_writer;use super::windows_common::start_runner_stdin_writer;use super::windows_common::start_runner_stdout_reader;use crate::identity::SandboxCreds;use crate::identity::refresh_logon_sandbox_creds;use crate::ipc_framed::EmptyPayload;use crate::ipc_framed::FramedMessage;use crate::ipc_framed::IPC_PROTOCOL_VERSION;use crate::ipc_framed::Message;use crate::ipc_framed::SpawnRequest;use crate::resolved_permissions::ResolvedWindowsSandboxPermissions;use crate::runner_client::RunnerTransport;use crate::runner_client::is_stale_sandbox_creds_error;use crate::runner_client::spawn_runner_transport;use crate::spawn_prep::prepare_elevated_spawn_context_for_permissions;use anyhow::Result;use codex_protocol::models::PermissionProfile;use codex_utils_absolute_path::AbsolutePathBuf;use codex_utils_pty::ProcessDriver;use codex_utils_pty::SpawnedProcess;use std::collections::HashMap;use std::path::Path;use std::path::PathBuf;use tokio::sync::broadcast;use tokio::sync::mpsc;use tokio::sync::oneshot;async fn spawn_runner_transport_task(    codex_home: PathBuf,    cwd: PathBuf,    sandbox_creds: SandboxCreds,    logs_base_dir: Option<PathBuf>,    spawn_request: SpawnRequest,) -> Result<RunnerTransport> {    tokio::task::spawn_blocking(move || -> Result<_> {        spawn_runner_transport(            &codex_home,            &cwd,            &sandbox_creds,            logs_base_dir.as_deref(),            spawn_request,        )    })    .await    .map_err(|err| anyhow::anyhow!("runner handshake task failed: {err}"))?}#[allow(clippy::too_many_arguments)]pub(crate) async fn spawn_windows_sandbox_session_elevated_for_permission_profile(    permission_profile: &PermissionProfile,    workspace_roots: &[AbsolutePathBuf],    codex_home: &Path,    command: Vec<String>,    cwd: &Path,    mut env_map: HashMap<String, String>,    proxy_enforced: bool,    timeout_ms: Option<u64>,    read_roots_override: Option<&[PathBuf]>,    read_roots_include_platform_defaults: bool,    write_roots_override: Option<&[PathBuf]>,    deny_read_paths_override: &[AbsolutePathBuf],    deny_write_paths_override: &[AbsolutePathBuf],    tty: bool,    stdin_open: bool,    use_private_desktop: bool,) -> Result<SpawnedProcess> {    let deny_read_paths_override = deny_read_paths_override        .iter()        .map(AbsolutePathBuf::to_path_buf)        .collect::<Vec<_>>();    let deny_write_paths_override = deny_write_paths_override        .iter()        .map(AbsolutePathBuf::to_path_buf)        .collect::<Vec<_>>();    let permissions =        ResolvedWindowsSandboxPermissions::try_from_permission_profile_for_workspace_roots(            permission_profile,            workspace_roots,        )?;    let elevated = prepare_elevated_spawn_context_for_permissions(        permissions.clone(),        codex_home,        cwd,        &mut env_map,        &command,        read_roots_override,        read_roots_include_platform_defaults,        write_roots_override,        &deny_read_paths_override,        &deny_write_paths_override,        proxy_enforced,    )?;    let spawn_request = SpawnRequest {        command: command.clone(),        cwd: cwd.to_path_buf(),        env: env_map.clone(),        permission_profile: permission_profile.clone(),        workspace_roots: workspace_roots.to_vec(),        codex_home: elevated.sandbox_base.clone(),        real_codex_home: codex_home.to_path_buf(),        cap_sids: elevated.cap_sids.clone(),        timeout_ms,        tty,        stdin_open,        use_private_desktop,    };    let codex_home = codex_home.to_path_buf();    let cwd = cwd.to_path_buf();    let sandbox_creds = elevated.sandbox_creds;    let logs_base_dir = elevated.logs_base_dir.clone();    let transport = match spawn_runner_transport_task(        codex_home.clone(),        cwd.clone(),        sandbox_creds,        logs_base_dir.clone(),        spawn_request.clone(),    )    .await    {        Ok(transport) => transport,        Err(err) if is_stale_sandbox_creds_error(&err) => {            let sandbox_creds = refresh_logon_sandbox_creds(                &permissions,                &cwd,                &env_map,                &codex_home,                read_roots_override,                read_roots_include_platform_defaults,                write_roots_override,                &deny_read_paths_override,                &deny_write_paths_override,                /*proxy_enforced*/ false,            )?;            spawn_runner_transport_task(                codex_home,                cwd,                sandbox_creds,                logs_base_dir,                spawn_request,            )            .await?        }        Err(err) => return Err(err),    };    let (pipe_write, pipe_read) = transport.into_files();    let (writer_tx, writer_rx) = mpsc::channel::<Vec<u8>>(128);    let (stdout_tx, stdout_rx) = broadcast::channel::<Vec<u8>>(256);    let stderr_rx = if tty {        None    } else {        Some(broadcast::channel::<Vec<u8>>(256))    };    let (exit_tx, exit_rx) = oneshot::channel::<i32>();    let outbound_tx = start_runner_pipe_writer(pipe_write);    let writer_handle = start_runner_stdin_writer(writer_rx, outbound_tx.clone(), tty, stdin_open);    let terminator = {        let outbound_tx = outbound_tx.clone();        Some(Box::new(move || {            let _ = outbound_tx.send(FramedMessage {                version: IPC_PROTOCOL_VERSION,                message: Message::Terminate {                    payload: EmptyPayload::default(),                },            });        }) as Box<dyn FnMut() + Send + Sync>)    };    start_runner_stdout_reader(        pipe_read,        stdout_tx,        stderr_rx.as_ref().map(|(tx, _rx)| tx.clone()),        exit_tx,    );    Ok(finish_driver_spawn(        ProcessDriver {            writer_tx,            stdout_rx,            stderr_rx: stderr_rx.map(|(_tx, rx)| rx),            exit_rx,            terminator,            writer_handle: Some(writer_handle),            resizer: if tty {                Some(make_runner_resizer(outbound_tx))            } else {                None            },        },        stdin_open,    ))}