mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-10 10:01:43 -10:00
fix(plugins): give the finalized stage root one non-inheriting ACL
The Windows log now names the inner verifier error: Codewhale-owned xAI OAuth DACL must grant only one user. The stage root's read/execute ACE carried CONTAINER_INHERIT_ACE and OBJECT_INHERIT_ACE; on a directory Windows stores that generic-rights ACE as more than one explicit ACE, which the protected owner-only verifier refuses. The finalized root uses NO_INHERITANCE because harden_staged_tree_contents has already given every descendant its own explicit read/execute ACL; the temporary staging root and plugin state directories keep inheriting ACEs. cargo fmt --check and cargo check -p codewhale-plugins --locked pass. A Windows-target check reached ring's C build and failed for the missing Windows SDK assert.h, not this code. The Windows suite remains red until this exact SHA runs.
This commit is contained in:
1 parent
34f8219bb1
commit
06a05bd75d
1 file changed
+37
-8
@@ -2512,10 +2512,10 @@ fn set_staged_read_only_directory(path: &Path) -> Result<(), String> {
|
||||
|
||||
#[cfg(windows)]
|
||||
fn set_staged_read_only_directory(path: &Path) -> Result<(), String> {
|
||||
// GENERIC_READ | GENERIC_EXECUTE. The owner can inspect/traverse the
|
||||
// finalized stage but ordinary child processes cannot rewrite it through
|
||||
// inherited full-control directory ACEs.
|
||||
set_windows_owner_only_acl_with_mask(path, 0xa000_0000)
|
||||
// GENERIC_READ | GENERIC_EXECUTE. Descendants are hardened explicitly, so
|
||||
// the root needs no inheriting ACE; an inheritable generic-rights ACE is
|
||||
// stored as more than one explicit ACE on a directory.
|
||||
set_windows_owner_only_acl_with_mask_and_inheritance(path, 0xa000_0000, false)
|
||||
}
|
||||
|
||||
#[cfg(all(not(unix), not(windows)))]
|
||||
@@ -2634,6 +2634,15 @@ fn open_windows_acl_target(
|
||||
|
||||
#[cfg(windows)]
|
||||
fn set_windows_owner_only_acl_with_mask(path: &Path, access_mask: u32) -> Result<(), String> {
|
||||
set_windows_owner_only_acl_with_mask_and_inheritance(path, access_mask, true)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn set_windows_owner_only_acl_with_mask_and_inheritance(
|
||||
path: &Path,
|
||||
access_mask: u32,
|
||||
inherit_to_children: bool,
|
||||
) -> Result<(), String> {
|
||||
const ACL_ACCESS_WITH_OWNER: u32 = 0x0002_0000 | 0x0004_0000 | 0x0008_0000;
|
||||
const ACL_ACCESS_WITHOUT_OWNER: u32 = 0x0002_0000 | 0x0004_0000;
|
||||
|
||||
@@ -2657,7 +2666,12 @@ fn set_windows_owner_only_acl_with_mask(path: &Path, access_mask: u32) -> Result
|
||||
Err(error) => return Err(error.into_message()),
|
||||
};
|
||||
|
||||
apply_windows_owner_only_acl(&target, access_mask, owner_mode)
|
||||
apply_windows_owner_only_acl_with_inheritance(
|
||||
&target,
|
||||
access_mask,
|
||||
owner_mode,
|
||||
inherit_to_children,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -2665,6 +2679,16 @@ fn apply_windows_owner_only_acl(
|
||||
target: &fs::File,
|
||||
access_mask: u32,
|
||||
owner_mode: WindowsAclOwnerMode,
|
||||
) -> Result<(), String> {
|
||||
apply_windows_owner_only_acl_with_inheritance(target, access_mask, owner_mode, true)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn apply_windows_owner_only_acl_with_inheritance(
|
||||
target: &fs::File,
|
||||
access_mask: u32,
|
||||
owner_mode: WindowsAclOwnerMode,
|
||||
inherit_to_children: bool,
|
||||
) -> Result<(), String> {
|
||||
use std::mem::{MaybeUninit, size_of};
|
||||
use std::os::windows::io::AsRawHandle as _;
|
||||
@@ -2672,7 +2696,7 @@ fn apply_windows_owner_only_acl(
|
||||
use windows::Win32::Security::Authorization::{SE_FILE_OBJECT, SetSecurityInfo};
|
||||
use windows::Win32::Security::{
|
||||
ACCESS_ALLOWED_ACE, ACL, ACL_REVISION, CONTAINER_INHERIT_ACE, DACL_SECURITY_INFORMATION,
|
||||
GetLengthSid, GetTokenInformation, InitializeAcl, OBJECT_INHERIT_ACE,
|
||||
GetLengthSid, GetTokenInformation, InitializeAcl, NO_INHERITANCE, OBJECT_INHERIT_ACE,
|
||||
OWNER_SECURITY_INFORMATION, PROTECTED_DACL_SECURITY_INFORMATION, TOKEN_QUERY, TOKEN_USER,
|
||||
TokenUser,
|
||||
};
|
||||
@@ -2723,11 +2747,16 @@ fn apply_windows_owner_only_acl(
|
||||
// containing the current user SID.
|
||||
unsafe { InitializeAcl(acl, acl_bytes as u32, ACL_REVISION) }
|
||||
.map_err(|error| format!("failed to initialize a private Windows ACL: {error}"))?;
|
||||
let inheritance = if inherit_to_children {
|
||||
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
||||
} else {
|
||||
NO_INHERITANCE
|
||||
};
|
||||
unsafe {
|
||||
windows::Win32::Security::AddAccessAllowedAceEx(
|
||||
acl,
|
||||
ACL_REVISION,
|
||||
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
|
||||
inheritance,
|
||||
access_mask,
|
||||
sid,
|
||||
)
|
||||
@@ -2864,7 +2893,7 @@ fn preserve_owner_only_file_mode(path: &Path, _source: &fs::Metadata) -> Result<
|
||||
// The protected handle-relative DACL is the Windows non-writable
|
||||
// authority. Avoid `set_permissions(path)`, which can follow a reparse
|
||||
// point substituted after metadata inspection.
|
||||
set_windows_owner_only_acl_with_mask(path, 0xa000_0000)
|
||||
set_windows_owner_only_acl_with_mask_and_inheritance(path, 0xa000_0000, false)
|
||||
}
|
||||
|
||||
#[cfg(all(not(unix), not(windows)))]
|
||||
|
||||
Reference in new issue
Block a user