diff --git a/codex-rs/windows-sandbox-rs/src/acl.rs b/codex-rs/windows-sandbox-rs/src/acl.rs index 68a17c9799..155ecf07bb 100644 --- a/codex-rs/windows-sandbox-rs/src/acl.rs +++ b/codex-rs/windows-sandbox-rs/src/acl.rs @@ -173,47 +173,6 @@ pub fn path_mask_allows( } } -pub unsafe fn dacl_has_write_allow_for_sid(p_dacl: *mut ACL, psid: *mut c_void) -> bool { - if p_dacl.is_null() { - return false; - } - let mut info: ACL_SIZE_INFORMATION = std::mem::zeroed(); - let ok = GetAclInformation( - p_dacl as *const ACL, - &mut info as *mut _ as *mut c_void, - std::mem::size_of::() as u32, - AclSizeInformation, - ); - if ok == 0 { - return false; - } - let count = info.AceCount as usize; - for i in 0..count { - let mut p_ace: *mut c_void = std::ptr::null_mut(); - if GetAce(p_dacl as *const ACL, i as u32, &mut p_ace) == 0 { - continue; - } - let hdr = &*(p_ace as *const ACE_HEADER); - if hdr.AceType != 0 { - continue; // ACCESS_ALLOWED_ACE_TYPE - } - // Ignore ACEs that are inherit-only (do not apply to the current object) - if (hdr.AceFlags & INHERIT_ONLY_ACE) != 0 { - continue; - } - let ace = &*(p_ace as *const ACCESS_ALLOWED_ACE); - let mask = ace.Mask; - let base = p_ace as usize; - let sid_ptr = - (base + std::mem::size_of::() + std::mem::size_of::()) as *mut c_void; - let eq = EqualSid(sid_ptr, psid); - if eq != 0 && (mask & FILE_GENERIC_WRITE) != 0 { - return true; - } - } - false -} - pub unsafe fn dacl_has_write_deny_for_sid(p_dacl: *mut ACL, psid: *mut c_void) -> bool { if p_dacl.is_null() { return false; @@ -374,70 +333,12 @@ pub unsafe fn ensure_allow_write_aces(path: &Path, sids: &[*mut c_void]) -> Resu ensure_allow_mask_aces(path, sids, WRITE_ALLOW_MASK) } -/// Adds an allow ACE granting read/write/execute to the given SID on the target path. +/// Adds an allow ACE granting the full sandbox write mask to the given SID on the target path. /// /// # Safety /// Caller must ensure `psid` points to a valid SID and `path` refers to an existing file or directory. pub unsafe fn add_allow_ace(path: &Path, psid: *mut c_void) -> Result { - let mut p_sd: *mut c_void = std::ptr::null_mut(); - let mut p_dacl: *mut ACL = std::ptr::null_mut(); - let code = GetNamedSecurityInfoW( - to_wide(path).as_ptr(), - 1, - DACL_SECURITY_INFORMATION, - std::ptr::null_mut(), - std::ptr::null_mut(), - &mut p_dacl, - std::ptr::null_mut(), - &mut p_sd, - ); - if code != ERROR_SUCCESS { - return Err(anyhow!("GetNamedSecurityInfoW failed: {code}")); - } - // Already has write? Skip costly DACL rewrite. - if dacl_has_write_allow_for_sid(p_dacl, psid) { - if !p_sd.is_null() { - LocalFree(p_sd as HLOCAL); - } - return Ok(false); - } - let mut added = false; - // Always ensure write is present: if an allow ACE exists without write, add one with write+RX. - let trustee = TRUSTEE_W { - pMultipleTrustee: std::ptr::null_mut(), - MultipleTrusteeOperation: 0, - TrusteeForm: TRUSTEE_IS_SID, - TrusteeType: TRUSTEE_IS_UNKNOWN, - ptstrName: psid as *mut u16, - }; - let mut explicit: EXPLICIT_ACCESS_W = std::mem::zeroed(); - explicit.grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE; - explicit.grfAccessMode = 2; // SET_ACCESS - explicit.grfInheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE; - explicit.Trustee = trustee; - let mut p_new_dacl: *mut ACL = std::ptr::null_mut(); - let code2 = SetEntriesInAclW(1, &explicit, p_dacl, &mut p_new_dacl); - if code2 == ERROR_SUCCESS { - let code3 = SetNamedSecurityInfoW( - to_wide(path).as_ptr() as *mut u16, - 1, - DACL_SECURITY_INFORMATION, - std::ptr::null_mut(), - std::ptr::null_mut(), - p_new_dacl, - std::ptr::null_mut(), - ); - if code3 == ERROR_SUCCESS { - added = !dacl_has_write_allow_for_sid(p_dacl, psid); - } - if !p_new_dacl.is_null() { - LocalFree(p_new_dacl as HLOCAL); - } - } - if !p_sd.is_null() { - LocalFree(p_sd as HLOCAL); - } - Ok(added) + ensure_allow_write_aces(path, &[psid]) } /// Adds a deny ACE to prevent write/append/delete for the given SID on the target path.