mirror of
https://github.com/openai/codex.git
synced 2026-05-05 05:42:33 +03:00
error code/msg details for failed elevated setup (#9941)
This commit is contained in:
@@ -9,6 +9,7 @@ use base64::Engine;
|
||||
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_write_aces;
|
||||
use codex_windows_sandbox::extract_setup_failure;
|
||||
use codex_windows_sandbox::hide_newly_created_users;
|
||||
use codex_windows_sandbox::load_or_create_cap_sids;
|
||||
use codex_windows_sandbox::log_note;
|
||||
@@ -17,6 +18,10 @@ use codex_windows_sandbox::sandbox_dir;
|
||||
use codex_windows_sandbox::sandbox_secrets_dir;
|
||||
use codex_windows_sandbox::string_from_sid_bytes;
|
||||
use codex_windows_sandbox::to_wide;
|
||||
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;
|
||||
@@ -89,7 +94,12 @@ enum SetupMode {
|
||||
|
||||
fn log_line(log: &mut File, msg: &str) -> Result<()> {
|
||||
let ts = chrono::Utc::now().to_rfc3339();
|
||||
writeln!(log, "[{ts}] {msg}")?;
|
||||
writeln!(log, "[{ts}] {msg}").map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperLogFailed,
|
||||
format!("failed to write setup log line: {err}"),
|
||||
))
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -349,29 +359,74 @@ pub fn main() -> Result<()> {
|
||||
fn real_main() -> Result<()> {
|
||||
let mut args = std::env::args().collect::<Vec<_>>();
|
||||
if args.len() != 2 {
|
||||
anyhow::bail!("expected payload argument");
|
||||
return Err(anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperRequestArgsFailed,
|
||||
"expected payload argument",
|
||||
)));
|
||||
}
|
||||
let payload_b64 = args.remove(1);
|
||||
let payload_json = BASE64
|
||||
.decode(payload_b64)
|
||||
.context("failed to decode payload b64")?;
|
||||
let payload: Payload =
|
||||
serde_json::from_slice(&payload_json).context("failed to parse payload json")?;
|
||||
let payload_json = BASE64.decode(payload_b64).map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperRequestArgsFailed,
|
||||
format!("failed to decode payload b64: {err}"),
|
||||
))
|
||||
})?;
|
||||
let payload: Payload = serde_json::from_slice(&payload_json).map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperRequestArgsFailed,
|
||||
format!("failed to parse payload json: {err}"),
|
||||
))
|
||||
})?;
|
||||
if payload.version != SETUP_VERSION {
|
||||
anyhow::bail!("setup version mismatch");
|
||||
return Err(anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperRequestArgsFailed,
|
||||
format!(
|
||||
"setup version mismatch: expected {SETUP_VERSION}, got {}",
|
||||
payload.version
|
||||
),
|
||||
)));
|
||||
}
|
||||
let sbx_dir = sandbox_dir(&payload.codex_home);
|
||||
std::fs::create_dir_all(&sbx_dir)?;
|
||||
std::fs::create_dir_all(&sbx_dir).map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperSandboxDirCreateFailed,
|
||||
format!("failed to create sandbox dir {}: {err}", sbx_dir.display()),
|
||||
))
|
||||
})?;
|
||||
let log_path = sbx_dir.join(LOG_FILE_NAME);
|
||||
let mut log = File::options()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(&log_path)
|
||||
.context("open log")?;
|
||||
.map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperLogFailed,
|
||||
format!("open log {} failed: {err}", log_path.display()),
|
||||
))
|
||||
})?;
|
||||
let result = run_setup(&payload, &mut log, &sbx_dir);
|
||||
if let Err(err) = &result {
|
||||
let _ = log_line(&mut log, &format!("setup error: {err:?}"));
|
||||
log_note(&format!("setup error: {err:?}"), Some(sbx_dir.as_path()));
|
||||
let failure = extract_setup_failure(err)
|
||||
.map(|f| SetupFailure::new(f.code, f.message.clone()))
|
||||
.unwrap_or_else(|| {
|
||||
SetupFailure::new(SetupErrorCode::HelperUnknownError, err.to_string())
|
||||
});
|
||||
let report = SetupErrorReport {
|
||||
code: failure.code,
|
||||
message: failure.message.clone(),
|
||||
};
|
||||
if let Err(write_err) = write_setup_error_report(&payload.codex_home, &report) {
|
||||
let _ = log_line(
|
||||
&mut log,
|
||||
&format!("setup error report write failed: {write_err}"),
|
||||
);
|
||||
log_note(
|
||||
&format!("setup error report write failed: {write_err}"),
|
||||
Some(sbx_dir.as_path()),
|
||||
);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -446,32 +501,77 @@ fn run_setup_full(payload: &Payload, log: &mut File, sbx_dir: &Path) -> Result<(
|
||||
let refresh_only = payload.refresh_only;
|
||||
if refresh_only {
|
||||
} else {
|
||||
provision_sandbox_users(
|
||||
let provision_result = provision_sandbox_users(
|
||||
&payload.codex_home,
|
||||
&payload.offline_username,
|
||||
&payload.online_username,
|
||||
log,
|
||||
)?;
|
||||
);
|
||||
if let Err(err) = provision_result {
|
||||
if extract_setup_failure(&err).is_some() {
|
||||
return Err(err);
|
||||
}
|
||||
return Err(anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperUserProvisionFailed,
|
||||
format!("provision sandbox users failed: {err}"),
|
||||
)));
|
||||
}
|
||||
let users = vec![
|
||||
payload.offline_username.clone(),
|
||||
payload.online_username.clone(),
|
||||
];
|
||||
hide_newly_created_users(&users, sbx_dir);
|
||||
}
|
||||
let offline_sid = resolve_sid(&payload.offline_username)?;
|
||||
let offline_sid = resolve_sid(&payload.offline_username).map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperSidResolveFailed,
|
||||
format!(
|
||||
"resolve SID for offline user {} failed: {err}",
|
||||
payload.offline_username
|
||||
),
|
||||
))
|
||||
})?;
|
||||
let offline_sid_str = string_from_sid_bytes(&offline_sid).map_err(anyhow::Error::msg)?;
|
||||
|
||||
let sandbox_group_sid = resolve_sandbox_users_group_sid()?;
|
||||
let sandbox_group_psid = sid_bytes_to_psid(&sandbox_group_sid)?;
|
||||
let sandbox_group_sid = resolve_sandbox_users_group_sid().map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperSidResolveFailed,
|
||||
format!("resolve sandbox users group SID failed: {err}"),
|
||||
))
|
||||
})?;
|
||||
let sandbox_group_psid = sid_bytes_to_psid(&sandbox_group_sid).map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperSidResolveFailed,
|
||||
format!("convert sandbox users group SID to PSID failed: {err}"),
|
||||
))
|
||||
})?;
|
||||
|
||||
let caps = load_or_create_cap_sids(&payload.codex_home)?;
|
||||
let caps = load_or_create_cap_sids(&payload.codex_home).map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperCapabilitySidFailed,
|
||||
format!("load or create capability SIDs failed: {err}"),
|
||||
))
|
||||
})?;
|
||||
let cap_psid = unsafe {
|
||||
convert_string_sid_to_sid(&caps.workspace)
|
||||
.ok_or_else(|| anyhow::anyhow!("convert capability SID failed"))?
|
||||
convert_string_sid_to_sid(&caps.workspace).ok_or_else(|| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperCapabilitySidFailed,
|
||||
format!("convert capability SID {} failed", caps.workspace),
|
||||
))
|
||||
})?
|
||||
};
|
||||
let mut refresh_errors: Vec<String> = Vec::new();
|
||||
if !refresh_only {
|
||||
firewall::ensure_offline_outbound_block(&offline_sid_str, log)?;
|
||||
let firewall_result = firewall::ensure_offline_outbound_block(&offline_sid_str, log);
|
||||
if let Err(err) = firewall_result {
|
||||
if extract_setup_failure(&err).is_some() {
|
||||
return Err(err);
|
||||
}
|
||||
return Err(anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperFirewallRuleCreateOrAddFailed,
|
||||
format!("ensure offline outbound block failed: {err}"),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
if payload.read_roots.is_empty() {
|
||||
@@ -482,14 +582,26 @@ fn run_setup_full(payload: &Payload, log: &mut File, sbx_dir: &Path) -> Result<(
|
||||
log_line(log, "read ACL helper already running; skipping spawn")?;
|
||||
}
|
||||
Ok(false) => {
|
||||
spawn_read_acl_helper(payload, log)?;
|
||||
spawn_read_acl_helper(payload, log).map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperReadAclHelperSpawnFailed,
|
||||
format!("spawn read ACL helper failed: {err}"),
|
||||
))
|
||||
})?;
|
||||
}
|
||||
Err(err) => {
|
||||
log_line(
|
||||
log,
|
||||
&format!("read ACL mutex check failed: {err}; spawning anyway"),
|
||||
)?;
|
||||
spawn_read_acl_helper(payload, log)?;
|
||||
spawn_read_acl_helper(payload, log).map_err(|spawn_err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperReadAclHelperSpawnFailed,
|
||||
format!(
|
||||
"spawn read ACL helper failed after mutex error {err}: {spawn_err}"
|
||||
),
|
||||
))
|
||||
})?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -615,14 +727,32 @@ fn run_setup_full(payload: &Payload, log: &mut File, sbx_dir: &Path) -> Result<(
|
||||
&sandbox_group_sid,
|
||||
GRANT_ACCESS,
|
||||
log,
|
||||
)?;
|
||||
)
|
||||
.map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperSandboxLockFailed,
|
||||
format!(
|
||||
"lock sandbox dir {} failed: {err}",
|
||||
sandbox_dir(&payload.codex_home).display()
|
||||
),
|
||||
))
|
||||
})?;
|
||||
lock_sandbox_dir(
|
||||
&sandbox_secrets_dir(&payload.codex_home),
|
||||
&payload.real_user,
|
||||
&sandbox_group_sid,
|
||||
DENY_ACCESS,
|
||||
log,
|
||||
)?;
|
||||
)
|
||||
.map_err(|err| {
|
||||
anyhow::Error::new(SetupFailure::new(
|
||||
SetupErrorCode::HelperSandboxLockFailed,
|
||||
format!(
|
||||
"lock sandbox secrets dir {} failed: {err}",
|
||||
sandbox_secrets_dir(&payload.codex_home).display()
|
||||
),
|
||||
))
|
||||
})?;
|
||||
let legacy_users = sandbox_dir(&payload.codex_home).join("sandbox_users.json");
|
||||
if legacy_users.exists() {
|
||||
let _ = std::fs::remove_file(&legacy_users);
|
||||
|
||||
Reference in New Issue
Block a user