feat: 完成扩展资源验收与同步服务部署

This commit is contained in:
2026-09-10 02:57:38 +08:00
parent 68dc78a45e
commit 6f3f84f021
27 changed files with 400 additions and 112 deletions
+40 -9
View File
@@ -60,13 +60,43 @@ impl Profile {
/// 并须在整个启动期间持有已验证的包句柄。这里不使用递归继承,每个目录和文件都要分别检查、授权。
/// 此操作只会添加一条 ACE,不会清理已有权限。
pub fn grant_package_read_execute(&self, object: &std::fs::File) -> Result<()> {
self.update_package_access(object, false)
use windows_sys::Win32::Storage::FileSystem::{FILE_GENERIC_EXECUTE, FILE_GENERIC_READ};
self.update_access(
object,
false,
FILE_GENERIC_READ | FILE_GENERIC_EXECUTE,
0,
true,
)
}
/// 授予当前实例修改其专用 scratch 目录及新建子对象的权限。
pub fn grant_scratch_modify(&self, object: &std::fs::File) -> Result<()> {
use windows_sys::Win32::{
Security::SUB_CONTAINERS_AND_OBJECTS_INHERIT,
Storage::FileSystem::{
DELETE, FILE_GENERIC_EXECUTE, FILE_GENERIC_READ, FILE_GENERIC_WRITE,
},
};
self.update_access(
object,
false,
FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | DELETE,
SUB_CONTAINERS_AND_OBJECTS_INHERIT,
false,
)
}
/// 使用最初持有的对象句柄,仅移除这个新实例对应的允许 ACE;其他安全主体的 ACL 保持不变。
pub fn revoke_package_access(&self, object: &std::fs::File) -> Result<()> {
self.update_package_access(object, true)
self.update_access(object, true, 0, 0, false)
}
fn update_package_access(&self, object: &std::fs::File, revoke: bool) -> Result<()> {
fn update_access(
&self,
object: &std::fs::File,
revoke: bool,
permissions: u32,
inheritance: u32,
reject_hardlinks: bool,
) -> Result<()> {
// 跨并发实例序列化 Host 读/合并/写操作。
let _lock = PACKAGE_ACL_LOCK
.lock()
@@ -77,7 +107,7 @@ impl Profile {
Security::{Authorization::*, DACL_SECURITY_INFORMATION},
Storage::FileSystem::{
GetFileInformationByHandle, BY_HANDLE_FILE_INFORMATION,
FILE_ATTRIBUTE_REPARSE_POINT, FILE_GENERIC_EXECUTE, FILE_GENERIC_READ,
FILE_ATTRIBUTE_REPARSE_POINT,
},
};
struct LocalAllocation(*mut core::ffi::c_void);
@@ -99,7 +129,7 @@ impl Profile {
{
return Err(HostError::new("EXTENSION_CONTAINER_ACL_OBJECT_INVALID"));
}
if metadata.is_file() && !revoke {
if metadata.is_file() && !revoke && reject_hardlinks {
let mut info = BY_HANDLE_FILE_INFORMATION::default();
if unsafe { GetFileInformationByHandle(object.as_raw_handle(), &mut info) } == 0
|| info.nNumberOfLinks != 1
@@ -127,9 +157,9 @@ impl Profile {
return Err(HostError::new("EXTENSION_CONTAINER_ACL_FAILED"));
}
let entry = EXPLICIT_ACCESS_W {
grfAccessPermissions: FILE_GENERIC_READ | FILE_GENERIC_EXECUTE,
grfAccessPermissions: permissions,
grfAccessMode: if revoke { REVOKE_ACCESS } else { GRANT_ACCESS },
grfInheritance: 0,
grfInheritance: inheritance,
Trustee: TRUSTEE_W {
TrusteeForm: TRUSTEE_IS_SID,
TrusteeType: TRUSTEE_IS_UNKNOWN,
@@ -973,7 +1003,7 @@ mod tests {
mcp_modes.push("mcp_deadline");
}
if resources {
mcp_modes.extend(["mcp_cpu", "mcp_memory", "mcp_processes"]);
mcp_modes.extend(["mcp_cpu", "mcp_memory", "mcp_processes", "mcp_scratch"]);
}
for mode in mcp_modes {
use std::sync::{
@@ -1093,10 +1123,11 @@ mod tests {
);
assert!(session.take_tools_changed());
}
"mcp_cpu" | "mcp_memory" | "mcp_processes" => {
"mcp_cpu" | "mcp_memory" | "mcp_processes" | "mcp_scratch" => {
let expected = match mode {
"mcp_memory" => "EXTENSION_RESOURCE_MEMORY_EXCEEDED",
"mcp_processes" => "EXTENSION_RESOURCE_PROCESSES_EXCEEDED",
"mcp_scratch" => "EXTENSION_RESOURCE_SCRATCH_EXCEEDED",
_ => "EXTENSION_RESOURCE_CPU_EXCEEDED",
};
assert_eq!(result.unwrap_err().code, expected);