Compare commits

...

1 Commits

Author SHA1 Message Date
David Wiesen
f52d02b8d3 Fix Windows sandbox owner-only temp dirs 2026-04-29 19:27:36 -07:00

View File

@@ -1,18 +1,18 @@
use crate::winutil::to_wide;
use anyhow::anyhow;
use anyhow::Result;
use anyhow::anyhow;
use std::ffi::c_void;
use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::Foundation::ERROR_SUCCESS;
use windows_sys::Win32::Foundation::GetLastError;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Foundation::HLOCAL;
use windows_sys::Win32::Foundation::LUID;
use windows_sys::Win32::Foundation::LocalFree;
use windows_sys::Win32::Security::AdjustTokenPrivileges;
use windows_sys::Win32::Security::Authorization::SetEntriesInAclW;
use windows_sys::Win32::Security::Authorization::EXPLICIT_ACCESS_W;
use windows_sys::Win32::Security::Authorization::GRANT_ACCESS;
use windows_sys::Win32::Security::Authorization::SetEntriesInAclW;
use windows_sys::Win32::Security::Authorization::TRUSTEE_IS_SID;
use windows_sys::Win32::Security::Authorization::TRUSTEE_IS_UNKNOWN;
use windows_sys::Win32::Security::Authorization::TRUSTEE_W;
@@ -24,8 +24,6 @@ use windows_sys::Win32::Security::GetTokenInformation;
use windows_sys::Win32::Security::LookupPrivilegeValueW;
use windows_sys::Win32::Security::SetTokenInformation;
use windows_sys::Win32::Security::TokenDefaultDacl;
use windows_sys::Win32::Security::TokenGroups;
use windows_sys::Win32::Security::ACL;
use windows_sys::Win32::Security::SID_AND_ATTRIBUTES;
use windows_sys::Win32::Security::TOKEN_ADJUST_DEFAULT;
@@ -35,6 +33,8 @@ use windows_sys::Win32::Security::TOKEN_ASSIGN_PRIMARY;
use windows_sys::Win32::Security::TOKEN_DUPLICATE;
use windows_sys::Win32::Security::TOKEN_PRIVILEGES;
use windows_sys::Win32::Security::TOKEN_QUERY;
use windows_sys::Win32::Security::TokenDefaultDacl;
use windows_sys::Win32::Security::TokenGroups;
use windows_sys::Win32::System::Threading::GetCurrentProcess;
const DISABLE_MAX_PRIVILEGE: u32 = 0x01;
@@ -134,11 +134,7 @@ pub unsafe fn convert_string_sid_to_sid(s: &str) -> Option<*mut c_void> {
}
let mut psid: *mut c_void = std::ptr::null_mut();
let ok = unsafe { ConvertStringSidToSidW(to_wide(s).as_ptr(), &mut psid) };
if ok != 0 {
Some(psid)
} else {
None
}
if ok != 0 { Some(psid) } else { None }
}
/// # Safety
@@ -167,6 +163,18 @@ pub unsafe fn get_current_token_for_restriction() -> Result<HANDLE> {
}
pub unsafe fn get_logon_sid_bytes(h_token: HANDLE) -> Result<Vec<u8>> {
unsafe fn copy_sid_bytes(psid: *mut c_void) -> Option<Vec<u8>> {
let sid_len = GetLengthSid(psid);
if sid_len == 0 {
return None;
}
let mut out = vec![0u8; sid_len as usize];
if CopySid(sid_len, out.as_mut_ptr() as *mut c_void, psid) == 0 {
return None;
}
Some(out)
}
unsafe fn scan_token_groups_for_logon(h: HANDLE) -> Option<Vec<u8>> {
let mut needed: u32 = 0;
GetTokenInformation(h, TokenGroups, std::ptr::null_mut(), 0, &mut needed);
@@ -194,16 +202,7 @@ pub unsafe fn get_logon_sid_bytes(h_token: HANDLE) -> Result<Vec<u8>> {
for i in 0..group_count {
let entry: SID_AND_ATTRIBUTES = std::ptr::read_unaligned(groups_ptr.add(i));
if (entry.Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID {
let sid = entry.Sid;
let sid_len = GetLengthSid(sid);
if sid_len == 0 {
return None;
}
let mut out = vec![0u8; sid_len as usize];
if CopySid(sid_len, out.as_mut_ptr() as *mut c_void, sid) == 0 {
return None;
}
return Some(out);
return copy_sid_bytes(entry.Sid);
}
}
None
@@ -250,6 +249,60 @@ pub unsafe fn get_logon_sid_bytes(h_token: HANDLE) -> Result<Vec<u8>> {
Err(anyhow!("Logon SID not present on token"))
}
pub unsafe fn get_token_user_sid_bytes(h_token: HANDLE) -> Result<Vec<u8>> {
#[repr(C)]
struct TokenUserInfo {
user: SID_AND_ATTRIBUTES,
}
const TOKEN_USER_CLASS: i32 = 1; // TokenUser
let mut needed: u32 = 0;
GetTokenInformation(
h_token,
TOKEN_USER_CLASS,
std::ptr::null_mut(),
0,
&mut needed,
);
if needed < std::mem::size_of::<TokenUserInfo>() as u32 {
return Err(anyhow!("TokenUser query returned no SID"));
}
let mut buf: Vec<u8> = vec![0u8; needed as usize];
let ok = GetTokenInformation(
h_token,
TOKEN_USER_CLASS,
buf.as_mut_ptr() as *mut c_void,
needed,
&mut needed,
);
if ok == 0 {
return Err(anyhow!(
"GetTokenInformation(TokenUser) failed: {}",
GetLastError()
));
}
let token_user = std::ptr::read_unaligned(buf.as_ptr() as *const TokenUserInfo);
let sid_len = GetLengthSid(token_user.user.Sid);
if sid_len == 0 {
return Err(anyhow!("GetLengthSid(TokenUser) failed"));
}
let mut out = vec![0u8; sid_len as usize];
if CopySid(
sid_len,
out.as_mut_ptr() as *mut c_void,
token_user.user.Sid,
) == 0
{
return Err(anyhow!("CopySid(TokenUser) failed"));
}
Ok(out)
}
unsafe fn enable_single_privilege(h_token: HANDLE, name: &str) -> Result<()> {
let mut luid = LUID {
LowPart: 0,
@@ -333,19 +386,26 @@ unsafe fn create_token_with_caps_from(
if psid_capabilities.is_empty() {
return Err(anyhow!("no capability SIDs provided"));
}
let mut user_sid_bytes = get_token_user_sid_bytes(base_token)?;
let psid_user = user_sid_bytes.as_mut_ptr() as *mut c_void;
let mut logon_sid_bytes = get_logon_sid_bytes(base_token)?;
let psid_logon = logon_sid_bytes.as_mut_ptr() as *mut c_void;
let mut everyone = world_sid()?;
let psid_everyone = everyone.as_mut_ptr() as *mut c_void;
// Exact order: Capabilities..., Logon, Everyone
// Exact order: Capabilities..., User, Logon, Everyone. Including the sandbox user SID in the
// restricting set lets owner-only ACLs (for example Python's 0o700 temp dirs) remain
// accessible to the same restricted identity without broadening inherited root grants.
let mut entries: Vec<SID_AND_ATTRIBUTES> =
vec![std::mem::zeroed(); psid_capabilities.len() + 2];
vec![std::mem::zeroed(); psid_capabilities.len() + 3];
for (i, psid) in psid_capabilities.iter().enumerate() {
entries[i].Sid = *psid;
entries[i].Attributes = 0;
}
let logon_idx = psid_capabilities.len();
let user_idx = psid_capabilities.len();
entries[user_idx].Sid = psid_user;
entries[user_idx].Attributes = 0;
let logon_idx = user_idx + 1;
entries[logon_idx].Sid = psid_logon;
entries[logon_idx].Attributes = 0;
entries[logon_idx + 1].Sid = psid_everyone;
@@ -368,7 +428,8 @@ unsafe fn create_token_with_caps_from(
return Err(anyhow!("CreateRestrictedToken failed: {}", GetLastError()));
}
let mut dacl_sids: Vec<*mut c_void> = Vec::with_capacity(psid_capabilities.len() + 2);
let mut dacl_sids: Vec<*mut c_void> = Vec::with_capacity(psid_capabilities.len() + 3);
dacl_sids.push(psid_user);
dacl_sids.push(psid_logon);
dacl_sids.push(psid_everyone);
dacl_sids.extend_from_slice(psid_capabilities);