Request read control when updating Windows sandbox ACLs (#40475)

## Why

`SetSecurityInfo` can reject a directory handle opened with only `WRITE_DAC`.

## What changed

- Request `READ_CONTROL` alongside `WRITE_DAC` when opening or creating a
  no-reparse sandbox directory.
- Add a Windows regression test that provisions and locks a plain sandbox
  directory through the handle-based ACL path.

GitOrigin-RevId: bd50dc54d4cc80e9609323ddb4ecc7e4780a31fb
This commit is contained in:
iceweasel-oai
2026-08-24 20:34:13 +00:00
committed by copyberry
parent 333beecd41
commit 3a211471d2
3 changed files with 36 additions and 1 deletions
@@ -1035,6 +1035,10 @@ fn run_setup_full(payload: &Payload, log: &mut dyn Write, sbx_dir: &Path) -> Res
Ok(())
}
#[cfg(test)]
#[path = "win_acl_tests.rs"]
mod acl_tests;
#[cfg(test)]
mod tests {
use super::Payload;
@@ -21,6 +21,7 @@ use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_NORMAL;
use windows_sys::Win32::Storage::FileSystem::FILE_SHARE_DELETE;
use windows_sys::Win32::Storage::FileSystem::FILE_SHARE_READ;
use windows_sys::Win32::Storage::FileSystem::FILE_SHARE_WRITE;
use windows_sys::Win32::Storage::FileSystem::READ_CONTROL;
use windows_sys::Win32::Storage::FileSystem::WRITE_DAC;
use windows_sys::Win32::System::IO::IO_STATUS_BLOCK;
use windows_sys::Win32::System::IO::IO_STATUS_BLOCK_0;
@@ -115,9 +116,10 @@ pub(super) fn open_or_create_no_reparse(path: &Path) -> Result<OwnedHandle> {
};
let mut handle = 0;
let status = unsafe {
// SetSecurityInfo can reject a WRITE_DAC-only directory handle.
NtCreateFile(
&mut handle,
WRITE_DAC,
READ_CONTROL | WRITE_DAC,
&object_attributes,
&mut io_status_block,
ptr::null(),
@@ -0,0 +1,29 @@
use super::DELETE;
use super::FILE_GENERIC_EXECUTE;
use super::FILE_GENERIC_READ;
use super::FILE_GENERIC_WRITE;
use super::GRANT_ACCESS;
use super::SetupMode;
use super::lock_sandbox_dir;
use super::resolve_sid;
#[test]
fn provision_only_locks_plain_directory_via_handle() {
let temp = tempfile::tempdir().expect("tempdir");
let sandbox_bin = temp.path().join(".sandbox-bin");
let real_user = std::env::var("USERNAME").unwrap_or_else(|_| "Administrators".to_string());
let real_sid = resolve_sid(&real_user).expect("resolve real user SID");
lock_sandbox_dir(
&sandbox_bin,
&real_user,
&real_sid,
GRANT_ACCESS,
FILE_GENERIC_READ | FILE_GENERIC_EXECUTE,
FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | DELETE,
SetupMode::ProvisionOnly,
)
.expect("lock sandbox bin via no-reparse handle");
assert!(sandbox_bin.is_dir());
}