Files
codex/codex-rs/windows-sandbox-rs/src/hide_users.rs
T
Charlie Marsh 7c9731c9af Enable --deny-warnings for cargo shear (#21616)
## Summary

In https://github.com/openai/codex/pull/21584, we disabled doctests for
crates that lack any doctests. We can enforce that property via `cargo
shear --deny-warnings`: crates that lack doctests will be flagged if
doctests are enabled, and crates with doctests will be flagged if
doctests are disabled.

A few additional notes:

- By adding `--deny-warnings`, `cargo shear` also flagged a number of
modules that were not reachable at all. Some of those have been removed.
- This PR removes a usage of `windows_modules!` (since `cargo shear` and
`rustfmt` couldn't see through it) in favor of simple `#[cfg(target_os =
"windows")]` macros. As a consequence, many of these files exhibit churn
in this PR, since they weren't being formatted by `rustfmt` at all on
main.
- Again, to make the code more analyzable, this PR also removes some
usages of `#[path = "cwd_junction.rs"]` in favor of a more standard
module structure. The bin sidecar structure is still retained, but,
e.g., `windows-sandbox-rs/src/bin/command_runner.rs‎` was moved to
`windows-sandbox-rs/src/bin/command_runner/main.rs`, and so on.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-05-08 20:29:00 +00:00

159 lines
5.2 KiB
Rust

use crate::logging::log_note;
use crate::winutil::format_last_error;
use crate::winutil::to_wide;
use anyhow::anyhow;
use std::ffi::OsStr;
use std::path::Path;
use std::path::PathBuf;
use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_HIDDEN;
use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_SYSTEM;
use windows_sys::Win32::Storage::FileSystem::GetFileAttributesW;
use windows_sys::Win32::Storage::FileSystem::INVALID_FILE_ATTRIBUTES;
use windows_sys::Win32::Storage::FileSystem::SetFileAttributesW;
use windows_sys::Win32::System::Registry::HKEY;
use windows_sys::Win32::System::Registry::HKEY_LOCAL_MACHINE;
use windows_sys::Win32::System::Registry::KEY_WRITE;
use windows_sys::Win32::System::Registry::REG_DWORD;
use windows_sys::Win32::System::Registry::REG_OPTION_NON_VOLATILE;
use windows_sys::Win32::System::Registry::RegCloseKey;
use windows_sys::Win32::System::Registry::RegCreateKeyExW;
use windows_sys::Win32::System::Registry::RegSetValueExW;
const USERLIST_KEY_PATH: &str =
r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList";
pub fn hide_newly_created_users(usernames: &[String], log_base: &Path) {
if usernames.is_empty() {
return;
}
if let Err(err) = hide_users_in_winlogon(usernames, log_base) {
log_note(
&format!("hide users: failed to update Winlogon UserList: {err}"),
Some(log_base),
);
}
}
/// Best-effort: hides the current sandbox user's profile directory once it exists.
///
/// Windows only creates profile directories when that user first logs in.
/// This intentionally runs in the command-runner (as the sandbox user) because
/// command running is what causes us to log in as a particular sandbox user.
pub fn hide_current_user_profile_dir(log_base: &Path) {
let Some(profile) = std::env::var_os("USERPROFILE") else {
return;
};
let profile_dir = PathBuf::from(profile);
if !profile_dir.exists() {
return;
}
match hide_directory(&profile_dir) {
Ok(true) => {
// Log only when we actually change attributes, so this stays one-time per profile dir.
log_note(
&format!(
"hide users: profile dir hidden for current user ({})",
profile_dir.display()
),
Some(log_base),
);
}
Ok(false) => {}
Err(err) => {
log_note(
&format!(
"hide users: failed to hide current user profile dir ({}): {err}",
profile_dir.display()
),
Some(log_base),
);
}
}
}
fn hide_users_in_winlogon(usernames: &[String], log_base: &Path) -> anyhow::Result<()> {
let key = create_userlist_key()?;
for username in usernames {
let name_w = to_wide(OsStr::new(username));
let value: u32 = 0;
let status = unsafe {
RegSetValueExW(
key,
name_w.as_ptr(),
0,
REG_DWORD,
&value as *const u32 as *const u8,
std::mem::size_of_val(&value) as u32,
)
};
if status != 0 {
log_note(
&format!(
"hide users: failed to set UserList value for {username}: {status} ({error})",
error = format_last_error(status as i32)
),
Some(log_base),
);
}
}
unsafe {
RegCloseKey(key);
}
Ok(())
}
fn create_userlist_key() -> anyhow::Result<HKEY> {
let key_path = to_wide(USERLIST_KEY_PATH);
let mut key: HKEY = 0;
let status = unsafe {
RegCreateKeyExW(
HKEY_LOCAL_MACHINE,
key_path.as_ptr(),
0,
std::ptr::null_mut(),
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
std::ptr::null_mut(),
&mut key,
std::ptr::null_mut(),
)
};
if status != 0 {
return Err(anyhow!(
"RegCreateKeyExW failed: {status} ({error})",
error = format_last_error(status as i32)
));
}
Ok(key)
}
/// Sets HIDDEN|SYSTEM on `path` if needed, returning whether it changed anything.
fn hide_directory(path: &Path) -> anyhow::Result<bool> {
let wide = to_wide(path);
let attrs = unsafe { GetFileAttributesW(wide.as_ptr()) };
if attrs == INVALID_FILE_ATTRIBUTES {
let err = unsafe { GetLastError() } as i32;
return Err(anyhow!(
"GetFileAttributesW failed for {}: {err} ({error})",
path.display(),
error = format_last_error(err)
));
}
let new_attrs = attrs | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
if new_attrs == attrs {
return Ok(false);
}
let ok = unsafe { SetFileAttributesW(wide.as_ptr(), new_attrs) };
if ok == 0 {
let err = unsafe { GetLastError() } as i32;
return Err(anyhow!(
"SetFileAttributesW failed for {}: {err} ({error})",
path.display(),
error = format_last_error(err)
));
}
Ok(true)
}