mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
## Why Elevated Windows sandboxes need stable managed-proxy ports while preserving the network policy and environment attribution of each sandboxed process. ## What changed - Keep shared HTTP and SOCKS5 loopback ingress listeners alive across managed-proxy instances. - Add a per-route restricting SID to elevated sandbox tokens and dispatch incoming connections to the matching proxy policy after attributing the client process. - Reject connections without exactly one registered route, remove routes when their proxy handle is dropped, and keep unsandboxed Windows launches off the managed ingress. - Provision the elevated sandbox with the configured proxy ports and local-binding setting, honoring the selected profile and CLI overrides. ## Testing - Add Windows unit tests for TCP ownership attribution, route selection, restricting-token propagation, and setup settings. - Add an end-to-end Windows test covering stable ports, isolated environment policies, HTTP and SOCKS5 routing, and route teardown. GitOrigin-RevId: 783fac6e0f904dc9bb1955b75d4a5895e8bb9690
70 lines
2.2 KiB
Rust
70 lines
2.2 KiB
Rust
use super::*;
|
|
use windows_sys::Win32::Security::EqualSid;
|
|
use windows_sys::Win32::Security::TokenRestrictedSids;
|
|
|
|
unsafe fn token_has_restricting_sid(token: HANDLE, expected_sid: *mut c_void) -> Result<bool> {
|
|
let mut needed = 0;
|
|
GetTokenInformation(
|
|
token,
|
|
TokenRestrictedSids,
|
|
std::ptr::null_mut(),
|
|
0,
|
|
&mut needed,
|
|
);
|
|
if needed == 0 {
|
|
return Err(anyhow!(
|
|
"GetTokenInformation(TokenRestrictedSids) size query failed: {}",
|
|
GetLastError()
|
|
));
|
|
}
|
|
|
|
let mut buffer = vec![0_u8; needed as usize];
|
|
if GetTokenInformation(
|
|
token,
|
|
TokenRestrictedSids,
|
|
buffer.as_mut_ptr().cast(),
|
|
needed,
|
|
&mut needed,
|
|
) == 0
|
|
{
|
|
return Err(anyhow!(
|
|
"GetTokenInformation(TokenRestrictedSids) failed: {}",
|
|
GetLastError()
|
|
));
|
|
}
|
|
|
|
let group_count = std::ptr::read_unaligned(buffer.as_ptr().cast::<u32>()) as usize;
|
|
let after_count = buffer.as_ptr().add(std::mem::size_of::<u32>()) as usize;
|
|
let align = std::mem::align_of::<SID_AND_ATTRIBUTES>();
|
|
let entries_addr = (after_count + (align - 1)) & !(align - 1);
|
|
let restricting_sids =
|
|
std::slice::from_raw_parts(entries_addr as *const SID_AND_ATTRIBUTES, group_count);
|
|
Ok(restricting_sids
|
|
.iter()
|
|
.any(|entry| EqualSid(entry.Sid, expected_sid) != 0))
|
|
}
|
|
|
|
#[test]
|
|
fn elevated_token_includes_network_proxy_restricting_sid() -> Result<()> {
|
|
let capability_sid = LocalSid::from_string("S-1-5-21-10-20-30-40")?;
|
|
let network_proxy_sid = LocalSid::from_string("S-1-5-21-50-60-70-80")?;
|
|
let base_token = unsafe { get_current_token_for_restriction()? };
|
|
let restricted_token = unsafe {
|
|
create_readonly_token_with_caps_and_user_from(
|
|
base_token,
|
|
&[capability_sid.as_ptr()],
|
|
&[network_proxy_sid.as_ptr()],
|
|
)?
|
|
};
|
|
|
|
let has_network_proxy_sid =
|
|
unsafe { token_has_restricting_sid(restricted_token, network_proxy_sid.as_ptr()) };
|
|
unsafe {
|
|
CloseHandle(restricted_token);
|
|
CloseHandle(base_token);
|
|
}
|
|
|
|
assert!(has_network_proxy_sid?);
|
|
Ok(())
|
|
}
|