mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 01:16:50 +00:00
sandbox: upstream sandbox
The crate depends on a prebuilt library. BUG=b:213170185 TEST=presubmit Change-Id: I810baa14afa53e88f6b2a739481a6d3656efc2e5 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3784338 Commit-Queue: Vikram Auradkar <auradkar@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
990a0ce365
commit
44a07970cb
9 changed files with 1471 additions and 0 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -463,6 +463,7 @@ dependencies = [
|
|||
"remain",
|
||||
"resources",
|
||||
"rutabaga_gfx",
|
||||
"sandbox",
|
||||
"scudo",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -1597,6 +1598,17 @@ version = "1.0.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||
|
||||
[[package]]
|
||||
name = "sandbox"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base",
|
||||
"prebuilts",
|
||||
"win_util",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scudo"
|
||||
version = "0.1.2"
|
||||
|
|
|
@ -104,6 +104,7 @@ exclude = [
|
|||
"common/io_uring",
|
||||
"common/p9",
|
||||
"common/sync",
|
||||
"sandbox",
|
||||
"tube_transporter",
|
||||
"win_util",
|
||||
"tools/examples/baremetal",
|
||||
|
@ -249,6 +250,7 @@ ctrlc = "*"
|
|||
futures = "0.3"
|
||||
gpu_display = { path = "gpu_display", optional = true }
|
||||
rand = "0.8"
|
||||
sandbox = { path = "sandbox" }
|
||||
tracing = { path = "tracing" }
|
||||
tube_transporter = { path = "tube_transporter" }
|
||||
winapi = "*"
|
||||
|
|
14
sandbox/Cargo.toml
Normal file
14
sandbox/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "sandbox"
|
||||
version = "0.1.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
base = { path = "../base" }
|
||||
win_util = { path = "../win_util"}
|
||||
winapi = { version = "*", features = ["everything", "std", "impl-default"] }
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "*"
|
||||
prebuilts = { path = "../prebuilts" }
|
448
sandbox/bindings.rs
Normal file
448
sandbox/bindings.rs
Normal file
|
@ -0,0 +1,448 @@
|
|||
// Copyright 2022 The ChromiumOS Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// If this file changes, update this file upstream and update windows pre-built libraries
|
||||
// that upstream uses.
|
||||
//
|
||||
// TODO(b/239836957): Add how to generate and update pre-built library.
|
||||
|
||||
#![allow(deref_nullptr)]
|
||||
|
||||
/* automatically generated by rust-bindgen 0.56.0 */
|
||||
|
||||
pub const JOB_OBJECT_UILIMIT_NONE: u32 = 0;
|
||||
pub const JOB_OBJECT_UILIMIT_HANDLES: u32 = 1;
|
||||
pub const JOB_OBJECT_UILIMIT_READCLIPBOARD: u32 = 2;
|
||||
pub const JOB_OBJECT_UILIMIT_WRITECLIPBOARD: u32 = 4;
|
||||
pub const JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS: u32 = 8;
|
||||
pub const JOB_OBJECT_UILIMIT_DISPLAYSETTINGS: u32 = 16;
|
||||
pub const JOB_OBJECT_UILIMIT_GLOBALATOMS: u32 = 32;
|
||||
pub const JOB_OBJECT_UILIMIT_DESKTOP: u32 = 64;
|
||||
pub const JOB_OBJECT_UILIMIT_EXITWINDOWS: u32 = 128;
|
||||
pub const JOB_OBJECT_UILIMIT_ALL: u32 = 255;
|
||||
pub type size_t = ::std::os::raw::c_ulonglong;
|
||||
pub type wchar_t = ::std::os::raw::c_ushort;
|
||||
pub type DWORD = ::std::os::raw::c_ulong;
|
||||
pub type HANDLE = *mut ::std::os::raw::c_void;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct _PROCESS_INFORMATION {
|
||||
pub hProcess: HANDLE,
|
||||
pub hThread: HANDLE,
|
||||
pub dwProcessId: DWORD,
|
||||
pub dwThreadId: DWORD,
|
||||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout__PROCESS_INFORMATION() {
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<_PROCESS_INFORMATION>(),
|
||||
24usize,
|
||||
concat!("Size of: ", stringify!(_PROCESS_INFORMATION))
|
||||
);
|
||||
assert_eq!(
|
||||
::std::mem::align_of::<_PROCESS_INFORMATION>(),
|
||||
8usize,
|
||||
concat!("Alignment of ", stringify!(_PROCESS_INFORMATION))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<_PROCESS_INFORMATION>())).hProcess as *const _ as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_PROCESS_INFORMATION),
|
||||
"::",
|
||||
stringify!(hProcess)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<_PROCESS_INFORMATION>())).hThread as *const _ as usize },
|
||||
8usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_PROCESS_INFORMATION),
|
||||
"::",
|
||||
stringify!(hThread)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe {
|
||||
&(*(::std::ptr::null::<_PROCESS_INFORMATION>())).dwProcessId as *const _ as usize
|
||||
},
|
||||
16usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_PROCESS_INFORMATION),
|
||||
"::",
|
||||
stringify!(dwProcessId)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { &(*(::std::ptr::null::<_PROCESS_INFORMATION>())).dwThreadId as *const _ as usize },
|
||||
20usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(_PROCESS_INFORMATION),
|
||||
"::",
|
||||
stringify!(dwThreadId)
|
||||
)
|
||||
);
|
||||
}
|
||||
pub type PROCESS_INFORMATION = _PROCESS_INFORMATION;
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum ResultCode {
|
||||
SBOX_ALL_OK = 0,
|
||||
SBOX_ERROR_GENERIC = 1,
|
||||
SBOX_ERROR_BAD_PARAMS = 2,
|
||||
SBOX_ERROR_UNSUPPORTED = 3,
|
||||
SBOX_ERROR_NO_SPACE = 4,
|
||||
SBOX_ERROR_INVALID_IPC = 5,
|
||||
SBOX_ERROR_FAILED_IPC = 6,
|
||||
SBOX_ERROR_NO_HANDLE = 7,
|
||||
SBOX_ERROR_UNEXPECTED_CALL = 8,
|
||||
SBOX_ERROR_WAIT_ALREADY_CALLED = 9,
|
||||
SBOX_ERROR_CHANNEL_ERROR = 10,
|
||||
SBOX_ERROR_CANNOT_CREATE_DESKTOP = 11,
|
||||
SBOX_ERROR_CANNOT_CREATE_WINSTATION = 12,
|
||||
SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION = 13,
|
||||
SBOX_ERROR_INVALID_APP_CONTAINER = 14,
|
||||
SBOX_ERROR_INVALID_CAPABILITY = 15,
|
||||
SBOX_ERROR_CANNOT_INIT_APPCONTAINER = 16,
|
||||
SBOX_ERROR_PROC_THREAD_ATTRIBUTES = 17,
|
||||
SBOX_ERROR_CREATE_PROCESS = 18,
|
||||
SBOX_ERROR_DELEGATE_PRE_SPAWN = 19,
|
||||
SBOX_ERROR_ASSIGN_PROCESS_TO_JOB_OBJECT = 20,
|
||||
SBOX_ERROR_SET_THREAD_TOKEN = 21,
|
||||
SBOX_ERROR_GET_THREAD_CONTEXT = 22,
|
||||
SBOX_ERROR_DUPLICATE_TARGET_INFO = 23,
|
||||
SBOX_ERROR_SET_LOW_BOX_TOKEN = 24,
|
||||
SBOX_ERROR_CREATE_FILE_MAPPING = 25,
|
||||
SBOX_ERROR_DUPLICATE_SHARED_SECTION = 26,
|
||||
SBOX_ERROR_MAP_VIEW_OF_SHARED_SECTION = 27,
|
||||
SBOX_ERROR_APPLY_ASLR_MITIGATIONS = 28,
|
||||
SBOX_ERROR_SETUP_BASIC_INTERCEPTIONS = 29,
|
||||
SBOX_ERROR_SETUP_INTERCEPTION_SERVICE = 30,
|
||||
SBOX_ERROR_INITIALIZE_INTERCEPTIONS = 31,
|
||||
SBOX_ERROR_SETUP_NTDLL_IMPORTS = 32,
|
||||
SBOX_ERROR_SETUP_HANDLE_CLOSER = 33,
|
||||
SBOX_ERROR_CANNOT_GET_WINSTATION = 34,
|
||||
SBOX_ERROR_CANNOT_QUERY_WINSTATION_SECURITY = 35,
|
||||
SBOX_ERROR_CANNOT_GET_DESKTOP = 36,
|
||||
SBOX_ERROR_CANNOT_QUERY_DESKTOP_SECURITY = 37,
|
||||
SBOX_ERROR_CANNOT_SETUP_INTERCEPTION_CONFIG_BUFFER = 38,
|
||||
SBOX_ERROR_CANNOT_COPY_DATA_TO_CHILD = 39,
|
||||
SBOX_ERROR_CANNOT_SETUP_INTERCEPTION_THUNK = 40,
|
||||
SBOX_ERROR_CANNOT_RESOLVE_INTERCEPTION_THUNK = 41,
|
||||
SBOX_ERROR_CANNOT_WRITE_INTERCEPTION_THUNK = 42,
|
||||
SBOX_ERROR_CANNOT_FIND_BASE_ADDRESS = 43,
|
||||
SBOX_ERROR_CREATE_APPCONTAINER = 44,
|
||||
SBOX_ERROR_CREATE_APPCONTAINER_ACCESS_CHECK = 45,
|
||||
SBOX_ERROR_CREATE_APPCONTAINER_CAPABILITY = 46,
|
||||
SBOX_ERROR_CANNOT_INIT_JOB = 47,
|
||||
SBOX_ERROR_INVALID_LOWBOX_SID = 48,
|
||||
SBOX_ERROR_CANNOT_CREATE_RESTRICTED_TOKEN = 49,
|
||||
SBOX_ERROR_CANNOT_SET_DESKTOP_INTEGRITY = 50,
|
||||
SBOX_ERROR_CANNOT_CREATE_LOWBOX_TOKEN = 51,
|
||||
SBOX_ERROR_CANNOT_MODIFY_LOWBOX_TOKEN_DACL = 52,
|
||||
SBOX_ERROR_CANNOT_CREATE_RESTRICTED_IMP_TOKEN = 53,
|
||||
SBOX_ERROR_CANNOT_DUPLICATE_PROCESS_HANDLE = 54,
|
||||
SBOX_ERROR_CANNOT_LOADLIBRARY_EXECUTABLE = 55,
|
||||
SBOX_ERROR_CANNOT_FIND_VARIABLE_ADDRESS = 56,
|
||||
SBOX_ERROR_CANNOT_WRITE_VARIABLE_VALUE = 57,
|
||||
SBOX_ERROR_INVALID_WRITE_VARIABLE_SIZE = 58,
|
||||
SBOX_ERROR_CANNOT_INIT_BROKERSERVICES = 59,
|
||||
SBOX_ERROR_CANNOT_UPDATE_JOB_PROCESS_LIMIT = 60,
|
||||
SBOX_ERROR_CANNOT_CREATE_LOWBOX_IMPERSONATION_TOKEN = 61,
|
||||
SBOX_ERROR_UNSANDBOXED_PROCESS = 62,
|
||||
SBOX_ERROR_LAST = 63,
|
||||
}
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum IntegrityLevel {
|
||||
INTEGRITY_LEVEL_SYSTEM = 0,
|
||||
INTEGRITY_LEVEL_HIGH = 1,
|
||||
INTEGRITY_LEVEL_MEDIUM = 2,
|
||||
INTEGRITY_LEVEL_MEDIUM_LOW = 3,
|
||||
INTEGRITY_LEVEL_LOW = 4,
|
||||
INTEGRITY_LEVEL_BELOW_LOW = 5,
|
||||
INTEGRITY_LEVEL_UNTRUSTED = 6,
|
||||
INTEGRITY_LEVEL_LAST = 7,
|
||||
}
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum TokenLevel {
|
||||
USER_LOCKDOWN = 0,
|
||||
USER_RESTRICTED = 1,
|
||||
USER_LIMITED = 2,
|
||||
USER_INTERACTIVE = 3,
|
||||
USER_RESTRICTED_NON_ADMIN = 4,
|
||||
USER_NON_ADMIN = 5,
|
||||
USER_RESTRICTED_SAME_ACCESS = 6,
|
||||
USER_UNPROTECTED = 7,
|
||||
USER_LAST = 8,
|
||||
}
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum JobLevel {
|
||||
JOB_LOCKDOWN = 0,
|
||||
JOB_RESTRICTED = 1,
|
||||
JOB_LIMITED_USER = 2,
|
||||
JOB_INTERACTIVE = 3,
|
||||
JOB_UNPROTECTED = 4,
|
||||
JOB_NONE = 5,
|
||||
}
|
||||
pub type MitigationFlags = u64;
|
||||
pub const MITIGATION_DEP: MitigationFlags = 1;
|
||||
pub const MITIGATION_DEP_NO_ATL_THUNK: MitigationFlags = 2;
|
||||
pub const MITIGATION_SEHOP: MitigationFlags = 4;
|
||||
pub const MITIGATION_RELOCATE_IMAGE: MitigationFlags = 8;
|
||||
pub const MITIGATION_RELOCATE_IMAGE_REQUIRED: MitigationFlags = 16;
|
||||
pub const MITIGATION_HEAP_TERMINATE: MitigationFlags = 32;
|
||||
pub const MITIGATION_BOTTOM_UP_ASLR: MitigationFlags = 64;
|
||||
pub const MITIGATION_HIGH_ENTROPY_ASLR: MitigationFlags = 128;
|
||||
pub const MITIGATION_STRICT_HANDLE_CHECKS: MitigationFlags = 256;
|
||||
pub const MITIGATION_DLL_SEARCH_ORDER: MitigationFlags = 512;
|
||||
pub const MITIGATION_HARDEN_TOKEN_IL_POLICY: MitigationFlags = 1024;
|
||||
pub const MITIGATION_WIN32K_DISABLE: MitigationFlags = 2048;
|
||||
pub const MITIGATION_EXTENSION_POINT_DISABLE: MitigationFlags = 4096;
|
||||
pub const MITIGATION_DYNAMIC_CODE_DISABLE: MitigationFlags = 8192;
|
||||
pub const MITIGATION_DYNAMIC_CODE_DISABLE_WITH_OPT_OUT: MitigationFlags = 16384;
|
||||
pub const MITIGATION_DYNAMIC_CODE_OPT_OUT_THIS_THREAD: MitigationFlags = 32768;
|
||||
pub const MITIGATION_NONSYSTEM_FONT_DISABLE: MitigationFlags = 65536;
|
||||
pub const MITIGATION_FORCE_MS_SIGNED_BINS: MitigationFlags = 131072;
|
||||
pub const MITIGATION_IMAGE_LOAD_NO_REMOTE: MitigationFlags = 262144;
|
||||
pub const MITIGATION_IMAGE_LOAD_NO_LOW_LABEL: MitigationFlags = 524288;
|
||||
pub const MITIGATION_IMAGE_LOAD_PREFER_SYS32: MitigationFlags = 1048576;
|
||||
pub const MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION: MitigationFlags = 2097152;
|
||||
pub const MITIGATION_CET_DISABLED: MitigationFlags = 4194304;
|
||||
pub const MITIGATION_KTM_COMPONENT: MitigationFlags = 8388608;
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum SubSystem {
|
||||
SUBSYS_FILES = 0,
|
||||
SUBSYS_NAMED_PIPES = 1,
|
||||
SUBSYS_PROCESS = 2,
|
||||
SUBSYS_REGISTRY = 3,
|
||||
SUBSYS_SYNC = 4,
|
||||
SUBSYS_WIN32K_LOCKDOWN = 5,
|
||||
SUBSYS_SIGNED_BINARY = 6,
|
||||
SUBSYS_SOCKET = 7,
|
||||
}
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum Semantics {
|
||||
FILES_ALLOW_ANY = 0,
|
||||
FILES_ALLOW_READONLY = 1,
|
||||
FILES_ALLOW_QUERY = 2,
|
||||
FILES_ALLOW_DIR_ANY = 3,
|
||||
NAMEDPIPES_ALLOW_ANY = 4,
|
||||
PROCESS_MIN_EXEC = 5,
|
||||
PROCESS_ALL_EXEC = 6,
|
||||
EVENTS_ALLOW_ANY = 7,
|
||||
EVENTS_ALLOW_READONLY = 8,
|
||||
REG_ALLOW_READONLY = 9,
|
||||
REG_ALLOW_ANY = 10,
|
||||
FAKE_USER_GDI_INIT = 11,
|
||||
SIGNED_ALLOW_LOAD = 12,
|
||||
SOCKET_ALLOW_BROKER = 13,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct BrokerServices {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TargetServices {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ProcessState {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TargetPolicy {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PolicyInfo {
|
||||
_unused: [u8; 0],
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_broker_init(broker: *mut BrokerServices) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_create_policy(broker: *mut BrokerServices) -> *mut TargetPolicy;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_release_policy(policy: *mut TargetPolicy);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_spawn_target(
|
||||
broker: *mut BrokerServices,
|
||||
exe_path: *const wchar_t,
|
||||
command_line: *const wchar_t,
|
||||
policy: *mut TargetPolicy,
|
||||
last_warning: *mut ResultCode,
|
||||
last_error: *mut DWORD,
|
||||
target: *mut PROCESS_INFORMATION,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_wait_for_all_targets(broker: *mut BrokerServices) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_target_init(target: *mut TargetServices) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_lower_token(target: *mut TargetServices);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_get_state(target: *mut TargetServices) -> *mut ProcessState;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn get_broker_services() -> *mut BrokerServices;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn get_target_services() -> *mut TargetServices;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_token_level(
|
||||
policy: *mut TargetPolicy,
|
||||
initial: TokenLevel,
|
||||
lockdown: TokenLevel,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_get_initial_token_level(policy: *mut TargetPolicy) -> TokenLevel;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_get_lockdown_token_level(policy: *mut TargetPolicy) -> TokenLevel;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_job_level(
|
||||
policy: *mut TargetPolicy,
|
||||
job_level: JobLevel,
|
||||
ui_exceptions: u32,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_get_job_level(policy: *mut TargetPolicy) -> JobLevel;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_job_memory_limit(policy: *mut TargetPolicy, memory_limit: size_t)
|
||||
-> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_integrity_level(policy: *mut TargetPolicy, level: IntegrityLevel)
|
||||
-> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_delayed_integrity_level(
|
||||
policy: *mut TargetPolicy,
|
||||
level: IntegrityLevel,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_get_integrity_level(policy: *mut TargetPolicy) -> IntegrityLevel;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_alternate_desktop(
|
||||
policy: *mut TargetPolicy,
|
||||
alternate_winstation: bool,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_create_alternate_desktop(
|
||||
policy: *mut TargetPolicy,
|
||||
alternate_winstation: bool,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_destroy_alternate_desktop(policy: *mut TargetPolicy);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_lowbox(policy: *mut TargetPolicy, sid: *const wchar_t) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_process_mitigations(
|
||||
policy: *mut TargetPolicy,
|
||||
flags: MitigationFlags,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_get_process_mitigations(policy: *mut TargetPolicy) -> MitigationFlags;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_delayed_process_mitigations(
|
||||
policy: *mut TargetPolicy,
|
||||
flags: MitigationFlags,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_get_delayed_process_mitigations(policy: *mut TargetPolicy) -> MitigationFlags;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_disconnect_csrss(policy: *mut TargetPolicy) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_strict_interceptions(policy: *mut TargetPolicy);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_stdout_handle(policy: *mut TargetPolicy, handle: HANDLE) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_stderr_handle(policy: *mut TargetPolicy, handle: HANDLE) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_add_rule(
|
||||
policy: *mut TargetPolicy,
|
||||
subsystem: SubSystem,
|
||||
semantics: Semantics,
|
||||
pattern: *const wchar_t,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_add_dll_to_unload(
|
||||
policy: *mut TargetPolicy,
|
||||
dll_name: *const wchar_t,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_add_kernel_object_to_close(
|
||||
policy: *mut TargetPolicy,
|
||||
handle_type: *const wchar_t,
|
||||
handle_name: *const wchar_t,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_add_handle_to_share(policy: *mut TargetPolicy, handle: HANDLE);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_set_lockdown_default_dacl(policy: *mut TargetPolicy);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_add_restricting_random_sid(policy: *mut TargetPolicy);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_add_app_container_profile(
|
||||
policy: *mut TargetPolicy,
|
||||
package_name: *const wchar_t,
|
||||
create_profile: bool,
|
||||
) -> ResultCode;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_get_policy_info(policy: *mut TargetPolicy) -> *mut PolicyInfo;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_release_policy_info(policy_info: *mut PolicyInfo);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn sbox_policy_info_json_string(
|
||||
policy_info: *mut PolicyInfo,
|
||||
) -> *const ::std::os::raw::c_char;
|
||||
}
|
52
sandbox/build.rs
Normal file
52
sandbox/build.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2022 The ChromiumOS Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
static PREBUILTS_VERSION_FILENAME: &str = "prebuilts_version";
|
||||
static SANDBOX_LIB: &str = "libsandbox.lib";
|
||||
|
||||
static BINDINGS_FILE: &str = "bindings.rs";
|
||||
|
||||
pub fn setup_windows_prebuilts() {
|
||||
println!("cargo:rustc-link-lib=dbghelp");
|
||||
println!("cargo:rustc-link-lib=gdi32");
|
||||
println!("cargo:rustc-link-lib=oleaut32");
|
||||
println!("cargo:rustc-link-lib=setupapi");
|
||||
println!("cargo:rustc-link-lib=shell32");
|
||||
println!("cargo:rustc-link-lib=user32");
|
||||
println!("cargo:rustc-link-lib=winmm");
|
||||
|
||||
if std::env::var("CARGO_CFG_DEBUG_ASSERTIONS").is_ok() {
|
||||
println!("cargo:rustc-link-lib=ucrtd");
|
||||
}
|
||||
|
||||
println!("cargo:rustc-link-lib=libsandbox");
|
||||
|
||||
println!("cargo:rerun-if-changed={}", BINDINGS_FILE);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if std::env::var("CARGO_CFG_WINDOWS").is_ok() {
|
||||
let version = std::fs::read_to_string(PREBUILTS_VERSION_FILENAME)
|
||||
.unwrap()
|
||||
.trim()
|
||||
.parse::<u32>()
|
||||
.unwrap();
|
||||
|
||||
// TODO(b:253039132) build sandbox prebuilts locally on windows from build.rs.
|
||||
let files = prebuilts::download_prebuilts("sandbox", version, &[SANDBOX_LIB]).unwrap();
|
||||
println!(
|
||||
r#"cargo:rustc-link-search={};{}"#,
|
||||
std::env::var("PATH").unwrap(),
|
||||
files
|
||||
.get(0)
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
);
|
||||
setup_windows_prebuilts();
|
||||
}
|
||||
}
|
1
sandbox/prebuilts_version
Normal file
1
sandbox/prebuilts_version
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
826
sandbox/src/lib.rs
Normal file
826
sandbox/src/lib.rs
Normal file
|
@ -0,0 +1,826 @@
|
|||
// Copyright 2022 The ChromiumOS Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#![cfg(windows)]
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Once;
|
||||
|
||||
use base::named_pipes;
|
||||
use base::AsRawDescriptor;
|
||||
use base::FromRawDescriptor;
|
||||
use base::SafeDescriptor;
|
||||
use win_util::win32_wide_string;
|
||||
|
||||
#[cfg_attr(windows, path = "../bindings.rs")]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[allow(deref_nullptr)]
|
||||
pub mod bindings;
|
||||
|
||||
pub mod policy;
|
||||
|
||||
pub use bindings::IntegrityLevel;
|
||||
pub use bindings::JobLevel;
|
||||
pub use bindings::MitigationFlags;
|
||||
pub use bindings::ResultCode;
|
||||
pub use bindings::Semantics;
|
||||
pub use bindings::SubSystem;
|
||||
pub use bindings::TokenLevel;
|
||||
|
||||
use bindings::DWORD;
|
||||
pub use bindings::MITIGATION_BOTTOM_UP_ASLR;
|
||||
pub use bindings::MITIGATION_CET_DISABLED;
|
||||
pub use bindings::MITIGATION_DEP;
|
||||
pub use bindings::MITIGATION_DEP_NO_ATL_THUNK;
|
||||
pub use bindings::MITIGATION_DLL_SEARCH_ORDER;
|
||||
pub use bindings::MITIGATION_DYNAMIC_CODE_DISABLE;
|
||||
pub use bindings::MITIGATION_DYNAMIC_CODE_DISABLE_WITH_OPT_OUT;
|
||||
pub use bindings::MITIGATION_DYNAMIC_CODE_OPT_OUT_THIS_THREAD;
|
||||
pub use bindings::MITIGATION_EXTENSION_POINT_DISABLE;
|
||||
pub use bindings::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
pub use bindings::MITIGATION_HARDEN_TOKEN_IL_POLICY;
|
||||
pub use bindings::MITIGATION_HEAP_TERMINATE;
|
||||
pub use bindings::MITIGATION_HIGH_ENTROPY_ASLR;
|
||||
pub use bindings::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL;
|
||||
pub use bindings::MITIGATION_IMAGE_LOAD_NO_REMOTE;
|
||||
pub use bindings::MITIGATION_IMAGE_LOAD_PREFER_SYS32;
|
||||
pub use bindings::MITIGATION_KTM_COMPONENT;
|
||||
pub use bindings::MITIGATION_NONSYSTEM_FONT_DISABLE;
|
||||
pub use bindings::MITIGATION_RELOCATE_IMAGE;
|
||||
pub use bindings::MITIGATION_RELOCATE_IMAGE_REQUIRED;
|
||||
pub use bindings::MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION;
|
||||
pub use bindings::MITIGATION_SEHOP;
|
||||
pub use bindings::MITIGATION_STRICT_HANDLE_CHECKS;
|
||||
pub use bindings::MITIGATION_WIN32K_DISABLE;
|
||||
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_ALL;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_DESKTOP;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_DISPLAYSETTINGS;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_EXITWINDOWS;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_GLOBALATOMS;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_HANDLES;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_NONE;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_READCLIPBOARD;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
|
||||
pub use bindings::JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
|
||||
|
||||
use bindings::PROCESS_INFORMATION;
|
||||
|
||||
type Result<T> = std::result::Result<T, SandboxError>;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct SandboxError {
|
||||
result_code: ResultCode,
|
||||
error_code: Option<u32>,
|
||||
}
|
||||
|
||||
impl fmt::Display for SandboxError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.error_code {
|
||||
Some(error_code) => write!(
|
||||
f,
|
||||
"Sandbox error code: {:?}, win32 error code: {}",
|
||||
self.result_code, error_code,
|
||||
),
|
||||
None => write!(f, "Sandbox error code: {:?}", self.result_code),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for SandboxError {
|
||||
fn description(&self) -> &str {
|
||||
"sandbox error"
|
||||
}
|
||||
}
|
||||
|
||||
impl SandboxError {
|
||||
pub fn new(result_code: ResultCode) -> SandboxError {
|
||||
if result_code == bindings::ResultCode::SBOX_ERROR_GENERIC {
|
||||
return SandboxError::from(std::io::Error::last_os_error());
|
||||
}
|
||||
SandboxError {
|
||||
result_code,
|
||||
error_code: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for SandboxError {
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
let error_code = error.raw_os_error().map(|e| e as u32);
|
||||
SandboxError {
|
||||
result_code: bindings::ResultCode::SBOX_ERROR_GENERIC,
|
||||
error_code,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type SandboxWarning = SandboxError;
|
||||
|
||||
/// Encapsulates broker-related functionality for the sandbox.
|
||||
///
|
||||
/// This struct and its methods are not thread safe, in general. Only a single
|
||||
/// thread should call the methods on this struct.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct BrokerServices {
|
||||
broker: *mut bindings::BrokerServices,
|
||||
}
|
||||
|
||||
/// Encapsulates target-related functionality for the sandbox.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct TargetServices {
|
||||
target: *mut bindings::TargetServices,
|
||||
}
|
||||
|
||||
/// Defines sandbox policies for target processes.
|
||||
pub struct TargetPolicy<'a> {
|
||||
policy: TargetPolicyWrapper,
|
||||
_marker: PhantomData<&'a dyn AsRawDescriptor>,
|
||||
}
|
||||
|
||||
struct TargetPolicyWrapper(*mut bindings::TargetPolicy);
|
||||
|
||||
impl Drop for TargetPolicyWrapper {
|
||||
fn drop(&mut self) {
|
||||
// Safe because TargetPolicyWrapper can only be constructed with a non-null pointer.
|
||||
unsafe { bindings::sbox_release_policy(self.0) };
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ProcessInformation {
|
||||
pub process: SafeDescriptor,
|
||||
pub thread: SafeDescriptor,
|
||||
pub process_id: u32,
|
||||
pub thread_id: u32,
|
||||
}
|
||||
|
||||
pub struct PolicyInfo {
|
||||
policy_info: *mut bindings::PolicyInfo,
|
||||
}
|
||||
|
||||
impl Drop for PolicyInfo {
|
||||
fn drop(&mut self) {
|
||||
unsafe { bindings::sbox_release_policy_info(self.policy_info) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this process is the broker process.
|
||||
pub fn is_sandbox_broker() -> bool {
|
||||
// Safe because the returned raw pointer is a non-owning pointer and we are free
|
||||
// to let it drop unmanaged.
|
||||
unsafe { !bindings::get_broker_services().is_null() }
|
||||
}
|
||||
|
||||
/// Returns true if this process is a target process.
|
||||
pub fn is_sandbox_target() -> bool {
|
||||
// Safe because the returned raw pointer is a non-owning pointer and we are
|
||||
// free to let it drop unmanaged.
|
||||
unsafe { !bindings::get_target_services().is_null() }
|
||||
}
|
||||
|
||||
impl BrokerServices {
|
||||
/// Returns an initialized broker API interface if the process is the broker.
|
||||
pub fn get() -> Result<Option<BrokerServices>> {
|
||||
static INIT: Once = Once::new();
|
||||
static mut RESULT: Result<()> = Ok(());
|
||||
static mut BROKER: Option<BrokerServices> = None;
|
||||
|
||||
// Initialize broker services. Should be called once before use.
|
||||
// Safe because RESULT is only written once, and call_once will cause
|
||||
// other readers to block until execution of the block is complete.
|
||||
// Also checks for and eliminates any null pointers.
|
||||
unsafe {
|
||||
INIT.call_once(|| {
|
||||
let broker = bindings::get_broker_services();
|
||||
if broker.is_null() {
|
||||
return;
|
||||
}
|
||||
BROKER = Some(BrokerServices { broker });
|
||||
RESULT = BROKER.as_mut().unwrap().init();
|
||||
});
|
||||
if BROKER.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
match RESULT {
|
||||
Err(e) => Err(e),
|
||||
Ok(_) => Ok(Some(BROKER.as_mut().unwrap().clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the broker. Must be called once before calling any other
|
||||
/// methods.
|
||||
///
|
||||
/// Takes a &mut self because sbox_broker_init mutates the underlying broker
|
||||
/// object.
|
||||
fn init(&mut self) -> Result<()> {
|
||||
// Safe because BrokerServices can only be constructed with a non-null
|
||||
// pointer.
|
||||
let result_code = unsafe { bindings::sbox_broker_init(self.broker) };
|
||||
if result_code != ResultCode::SBOX_ALL_OK {
|
||||
Err(SandboxError::new(result_code))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new policy object.
|
||||
pub fn create_policy<'a>(&self) -> TargetPolicy<'a> {
|
||||
// Safe because BrokerServices can only be constructed with a non-null pointer.
|
||||
let policy = unsafe { bindings::sbox_create_policy(self.broker) };
|
||||
TargetPolicy {
|
||||
policy: TargetPolicyWrapper(policy),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn a new target process. This process is created with the main thread
|
||||
/// in a suspended state.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_spawn_target()` mutates the underlying
|
||||
/// broker object.
|
||||
pub fn spawn_target(
|
||||
&mut self,
|
||||
exe_path: &str,
|
||||
command_line: &str,
|
||||
policy: &TargetPolicy,
|
||||
) -> Result<(ProcessInformation, Option<SandboxWarning>)> {
|
||||
let mut last_warning = ResultCode::SBOX_ALL_OK;
|
||||
let mut last_error: DWORD = 0;
|
||||
let mut target = PROCESS_INFORMATION {
|
||||
dwProcessId: 0,
|
||||
dwThreadId: 0,
|
||||
hThread: std::ptr::null_mut(),
|
||||
hProcess: std::ptr::null_mut(),
|
||||
};
|
||||
// Safe because the external arguments must be constructed in a safe
|
||||
// way, and the rest of the arguments are pointers to valid objects
|
||||
// created in this function.
|
||||
let result = unsafe {
|
||||
bindings::sbox_spawn_target(
|
||||
self.broker,
|
||||
win32_wide_string(exe_path).as_ptr(),
|
||||
win32_wide_string(command_line).as_ptr(),
|
||||
policy.policy.0,
|
||||
&mut last_warning,
|
||||
&mut last_error,
|
||||
&mut target,
|
||||
)
|
||||
};
|
||||
if result != ResultCode::SBOX_ALL_OK {
|
||||
return Err(SandboxError {
|
||||
result_code: result,
|
||||
error_code: Some(last_error),
|
||||
});
|
||||
}
|
||||
// Safe because we are adopting the process and thread handles here,
|
||||
// and they won't be used outside of the SafeDescriptor after this
|
||||
// function returns.
|
||||
let process = unsafe {
|
||||
ProcessInformation {
|
||||
process: SafeDescriptor::from_raw_descriptor(target.hProcess),
|
||||
thread: SafeDescriptor::from_raw_descriptor(target.hThread),
|
||||
process_id: target.dwProcessId,
|
||||
thread_id: target.dwThreadId,
|
||||
}
|
||||
};
|
||||
if last_warning != ResultCode::SBOX_ALL_OK {
|
||||
Ok((
|
||||
process,
|
||||
Some(SandboxWarning {
|
||||
result_code: last_warning,
|
||||
error_code: Some(last_error),
|
||||
}),
|
||||
))
|
||||
} else {
|
||||
Ok((process, None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits (blocks) for all target processes to exit.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_wait_for_all_targets()` mutates the
|
||||
/// underlying broker object.
|
||||
pub fn wait_for_all_targets(&mut self) -> Result<()> {
|
||||
// Safe because BrokerServices can only be constructed with a non-null pointer.
|
||||
let result_code = unsafe { bindings::sbox_wait_for_all_targets(self.broker) };
|
||||
if result_code != ResultCode::SBOX_ALL_OK {
|
||||
Err(SandboxError::new(result_code))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TargetServices {
|
||||
/// Returns an initialized target API interface if the process is the target.
|
||||
pub fn get() -> Result<Option<TargetServices>> {
|
||||
static INIT: Once = Once::new();
|
||||
static mut RESULT: Result<()> = Ok(());
|
||||
static mut TARGET: Option<TargetServices> = None;
|
||||
|
||||
// Initialize target services. Should be called once before use.
|
||||
// Safe because RESULT is only written once, and call_once will cause
|
||||
// other readers to block until execution of the block is complete.
|
||||
// Also checks for and eliminates any null pointers.
|
||||
unsafe {
|
||||
INIT.call_once(|| {
|
||||
let target = bindings::get_target_services();
|
||||
if target.is_null() {
|
||||
return;
|
||||
}
|
||||
TARGET = Some(TargetServices { target });
|
||||
RESULT = TARGET.as_mut().unwrap().init()
|
||||
});
|
||||
if TARGET.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
// Initialize target services. If TargetServices is already initialized,
|
||||
// this is a no-op.
|
||||
match RESULT {
|
||||
Err(e) => Err(e),
|
||||
Ok(_) => Ok(Some(TARGET.as_mut().unwrap().clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the target. Must be called once before calling any other
|
||||
/// methods.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_target_init()` mutates the underlying
|
||||
/// target object.
|
||||
fn init(&mut self) -> Result<()> {
|
||||
// Safe because TargetServices can only be constructed with a non-null pointer.
|
||||
let result_code = unsafe { bindings::sbox_target_init(self.target) };
|
||||
if result_code != ResultCode::SBOX_ALL_OK {
|
||||
Err(SandboxError::new(result_code))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Discards the targets impersonation token and uses the lower token.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_lower_token()` mutates the underlying
|
||||
/// target object.
|
||||
pub fn lower_token(&mut self) {
|
||||
// Safe because TargetServices can only be constructed with a non-null pointer.
|
||||
unsafe { bindings::sbox_lower_token(self.target) };
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TargetPolicy<'a> {
|
||||
/// Sets the security level for the process' two tokens.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_token_level()` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn set_token_level(&mut self, initial: TokenLevel, lockdown: TokenLevel) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_token_level(self.policy.0, initial, lockdown) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the initial token level.
|
||||
pub fn initial_token_level(&self) -> TokenLevel {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe { bindings::sbox_get_initial_token_level(self.policy.0) }
|
||||
}
|
||||
|
||||
/// Gets the lockdown token level.
|
||||
pub fn lockdown_token_level(&self) -> TokenLevel {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe { bindings::sbox_get_lockdown_token_level(self.policy.0) }
|
||||
}
|
||||
|
||||
/// Sets the security level of the job object to which the process will
|
||||
/// belong.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_job_level()` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn set_job_level(&mut self, job_level: JobLevel, ui_exceptions: u32) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_job_level(self.policy.0, job_level, ui_exceptions) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the job level.
|
||||
pub fn job_level(&self) -> JobLevel {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe { bindings::sbox_get_job_level(self.policy.0) }
|
||||
}
|
||||
|
||||
/// Sets the initial integrity level of the process in the sandbox.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_integrity_level()` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn set_integrity_level(&mut self, level: IntegrityLevel) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_integrity_level(self.policy.0, level) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the delayed integrity level of the process in the sandbox.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_delayed_integrity_level()` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn set_delayed_integrity_level(&mut self, level: IntegrityLevel) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_delayed_integrity_level(self.policy.0, level) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the initial integrity level used.
|
||||
pub fn integrity_level(&self) -> IntegrityLevel {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe { bindings::sbox_get_integrity_level(self.policy.0) }
|
||||
}
|
||||
|
||||
/// Specifies that the process should run on an alternate desktop. If
|
||||
/// `alternate_winstation` is set to `true`, the desktop will be created on an
|
||||
/// alternate windows station.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_alternate_desktop` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn set_alternate_desktop(&mut self, alternate_winstation: bool) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_alternate_desktop(self.policy.0, alternate_winstation) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Precreates the alternate desktop and winstation, if any.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_create_alternate_desktop` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn create_alternate_desktop(&mut self, alternate_winstation: bool) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe {
|
||||
bindings::sbox_create_alternate_desktop(self.policy.0, alternate_winstation)
|
||||
} {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroys the desktop and windows station.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_destroy_alternate_desktop` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn destroy_alternate_desktop(&mut self) {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe { bindings::sbox_destroy_alternate_desktop(self.policy.0) }
|
||||
}
|
||||
|
||||
/// Sets the LowBox token for sandboxed process. This is mutually exclusive
|
||||
/// with the `add_app_container_profile()` method.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_lowbox` mutates the underlying
|
||||
/// policy object.
|
||||
pub fn set_lowbox(&mut self, sid: &str) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_lowbox(self.policy.0, win32_wide_string(sid).as_ptr()) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the mitigations enabled when the process is created.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_process_mitigations` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn set_process_mitigations(&mut self, flags: MitigationFlags) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_process_mitigations(self.policy.0, flags) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the currently set mitigation flags.
|
||||
pub fn process_mitigations(&self) -> MitigationFlags {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe { bindings::sbox_get_process_mitigations(self.policy.0) }
|
||||
}
|
||||
|
||||
/// Sets process mitigation flags that don't take effect before the call to
|
||||
/// lower_token().
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_delayed_process_mitigations`
|
||||
/// mutates the underlying policy object.
|
||||
pub fn set_delayed_process_mitigations(&mut self, flags: MitigationFlags) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_delayed_process_mitigations(self.policy.0, flags) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the currently set delayed_ mitigation flags.
|
||||
pub fn delayed_process_mitigations(&self) -> MitigationFlags {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe { bindings::sbox_get_delayed_process_mitigations(self.policy.0) }
|
||||
}
|
||||
|
||||
/// Disconnect the target from CSRSS when TargetServices::lower_token() is
|
||||
/// called inside the target.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_disconnect_csrss` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn set_disconnect_csrss(&mut self) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_disconnect_csrss(self.policy.0) } {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the interceptions to operate in strict mode.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_delayed_process_mitigations`
|
||||
/// mutates the underlying policy object.
|
||||
pub fn set_strict_interceptions(&mut self) {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe { bindings::sbox_set_strict_interceptions(self.policy.0) }
|
||||
}
|
||||
|
||||
/// Sets a file as the handle that the process should inherit for stdout.
|
||||
pub fn set_stdout_from_file(&mut self, file: &'a std::fs::File) -> Result<()> {
|
||||
self.set_stdout_handle(file)
|
||||
}
|
||||
|
||||
/// Sets a pipe as the handle that the process should inherit for stdout.
|
||||
pub fn set_stdout_from_pipe(&mut self, pipe: &'a named_pipes::PipeConnection) -> Result<()> {
|
||||
self.set_stdout_handle(pipe)
|
||||
}
|
||||
|
||||
/// Sets the handle that the process should inherit for stdout.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_stdout_handle()` mutates the underlying policy object.
|
||||
fn set_stdout_handle(&mut self, handle: &'a dyn AsRawDescriptor) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_stdout_handle(self.policy.0, handle.as_raw_descriptor()) }
|
||||
{
|
||||
ResultCode::SBOX_ALL_OK => {
|
||||
win_util::set_handle_inheritance(
|
||||
handle.as_raw_descriptor(),
|
||||
/* inheritable= */ true,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets a file as the handle that the process should inherit for stderr.
|
||||
pub fn set_stderr_from_file(&mut self, file: &'a std::fs::File) -> Result<()> {
|
||||
self.set_stderr_handle(file)
|
||||
}
|
||||
|
||||
/// Sets a pipe as the handle that the process should inherit for stderr.
|
||||
pub fn set_stderr_from_pipe(&mut self, pipe: &'a named_pipes::PipeConnection) -> Result<()> {
|
||||
self.set_stderr_handle(pipe)
|
||||
}
|
||||
|
||||
/// Sets the handle that the process should inherit for stderr.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_stderr_handle` mutates the underlying policy object.
|
||||
fn set_stderr_handle(&mut self, handle: &'a dyn AsRawDescriptor) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
match unsafe { bindings::sbox_set_stderr_handle(self.policy.0, handle.as_raw_descriptor()) }
|
||||
{
|
||||
ResultCode::SBOX_ALL_OK => {
|
||||
win_util::set_handle_inheritance(
|
||||
handle.as_raw_descriptor(),
|
||||
/* inheritable= */ true,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a policy rule effective for processes spawned using this policy.
|
||||
///
|
||||
/// # Arguments:
|
||||
///
|
||||
/// * subsystem: One of the enumerated Subsystems.
|
||||
/// * semantics: One of the enumerated Semantics.
|
||||
/// * pattern: A specific full path or a full path with wildcard patterns.
|
||||
///
|
||||
/// The valid wildcards are:
|
||||
/// * `*`: Matches zero or more character. Only one in series allowed.
|
||||
/// * `?`: Matches a single character. One or more in series are allowed.
|
||||
///
|
||||
/// Examples:
|
||||
/// * `"c:\\documents and settings\\vince\\*.dmp"`
|
||||
/// * `"c:\\documents and settings\\*\\crashdumps\\*.dmp"`
|
||||
/// * `"c:\\temp\\app_log_?????_chrome.txt"`
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_add_rule` mutates the underlying
|
||||
/// policy object.
|
||||
pub fn add_rule<T: AsRef<str>>(
|
||||
&mut self,
|
||||
subsystem: SubSystem,
|
||||
semantics: Semantics,
|
||||
pattern: T,
|
||||
) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
// The function does not modify the pattern pointer, so that usage is safe.
|
||||
match unsafe {
|
||||
bindings::sbox_add_rule(
|
||||
self.policy.0,
|
||||
subsystem,
|
||||
semantics,
|
||||
win32_wide_string(pattern.as_ref()).as_ptr(),
|
||||
)
|
||||
} {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a dll that will be unloaded in the target process before it gets
|
||||
/// a chance to initialize itself.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_add_dll_to_unload` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn add_dll_to_unload(&mut self, dll_name: &str) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
// The function does not modify the dll_name pointer, so that usage is safe.
|
||||
match unsafe {
|
||||
bindings::sbox_add_dll_to_unload(self.policy.0, win32_wide_string(dll_name).as_ptr())
|
||||
} {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handle that will be closed in the target process after lockdown.
|
||||
/// Specifying `None` for `handle_name` indicates all handles of the specified
|
||||
/// type. An empty string for `handle_name` indicates the handle is unnamed.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_add_kernel_object_to_close` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn add_kernel_object_to_close(
|
||||
&mut self,
|
||||
handle_type: &str,
|
||||
handle_name: Option<&str>,
|
||||
) -> Result<()> {
|
||||
let handle_name_wide = handle_name.map(win32_wide_string);
|
||||
let handle_name_ptr = handle_name_wide
|
||||
.as_ref()
|
||||
.map_or(std::ptr::null(), Vec::<u16>::as_ptr);
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
// The function does not modify either of the string pointers, so that usage is safe.
|
||||
// The function safely handles null pointers for the handle name.
|
||||
match unsafe {
|
||||
bindings::sbox_add_kernel_object_to_close(
|
||||
self.policy.0,
|
||||
win32_wide_string(handle_type).as_ptr(),
|
||||
handle_name_ptr,
|
||||
)
|
||||
} {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a handle that will be shared with the target process.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_add_handle_to_share()` mutates the underlying policy object.
|
||||
pub fn add_handle_to_share(&mut self, handle: &'a dyn AsRawDescriptor) {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe {
|
||||
bindings::sbox_add_handle_to_share(self.policy.0, handle.as_raw_descriptor());
|
||||
}
|
||||
}
|
||||
|
||||
/// Locks down the default DACL of the created lockdown and initial tokens
|
||||
/// to restrict what other processes are allowed to access a process' kernel
|
||||
/// resources.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_set_lockdown_default_dacl()` mutates
|
||||
/// the underlying policy object.
|
||||
pub fn set_lockdown_default_dacl(&mut self) {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe {
|
||||
bindings::sbox_set_lockdown_default_dacl(self.policy.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a restricting random SID to the restricted SIDs list as well as
|
||||
/// the default DACL.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_add_restricting_random_sid()` mutates
|
||||
/// the underlying policy object.
|
||||
pub fn add_restricting_random_sid(&mut self) {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
unsafe {
|
||||
bindings::sbox_add_restricting_random_sid(self.policy.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure policy to use an AppContainer profile.
|
||||
///
|
||||
/// # Arguments:
|
||||
/// * `package_name`: the name of the profile to use.
|
||||
/// * `create_profile`: Specifying `true` for `create_profile` ensures
|
||||
/// the profile exists, if set to `false` process creation will fail if the
|
||||
/// profile has not already been created.
|
||||
///
|
||||
/// Takes a `&mut self` because `sbox_add_dll_to_unload` mutates the
|
||||
/// underlying policy object.
|
||||
pub fn add_app_container_profile(
|
||||
&mut self,
|
||||
package_name: &str,
|
||||
create_profile: bool,
|
||||
) -> Result<()> {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null policy pointer.
|
||||
// The function does not modify the package_name pointer, so that usage is safe.
|
||||
match unsafe {
|
||||
bindings::sbox_add_app_container_profile(
|
||||
self.policy.0,
|
||||
win32_wide_string(package_name).as_ptr(),
|
||||
create_profile,
|
||||
)
|
||||
} {
|
||||
ResultCode::SBOX_ALL_OK => Ok(()),
|
||||
result_code => Err(SandboxError::new(result_code)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a snapshot of the policy configuration.
|
||||
pub fn policy_info(&self) -> PolicyInfo {
|
||||
// Safe because TargetPolicy can only be constructed with a non-null
|
||||
// policy pointer. The underlying PolicyInfo object contains a copy of
|
||||
// the data from the TargetPolicy object, but does not hold any
|
||||
// references to it, so the lifetimes are independent.
|
||||
PolicyInfo {
|
||||
policy_info: unsafe { bindings::sbox_get_policy_info(self.policy.0) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PolicyInfo {
|
||||
/// Returns a JSON representation of the policy snapshot.
|
||||
/// This pointer has the same lifetime as the PolicyInfo object.
|
||||
pub fn json(&self) -> &str {
|
||||
// Safe because PolicyInfo can only be constructed with a non-null
|
||||
// policy pointer. The string returned will be a valid pointer to a
|
||||
// valid c string. We bind the lifetime of the string to the lifetime
|
||||
// of the PolicyInfo object, as is guaranteed by the underlying
|
||||
// library. This is a string representation of a snapshot of the
|
||||
// policy, so it will not change.
|
||||
let c_str =
|
||||
unsafe { CStr::from_ptr(bindings::sbox_policy_info_json_string(self.policy_info)) };
|
||||
c_str.to_str().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/196996588): Develop more tests, especially policy-related, once we
|
||||
// have a way to launch and test target processes.
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn not_the_target() {
|
||||
let target = TargetServices::get().unwrap();
|
||||
assert_eq!(target, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_the_broker() {
|
||||
let broker = BrokerServices::get().unwrap();
|
||||
assert_ne!(broker, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn policy_handles_live_long_enough() {
|
||||
let broker = BrokerServices::get().unwrap().unwrap();
|
||||
let mut policy = broker.create_policy();
|
||||
let pipe = named_pipes::pair(
|
||||
&named_pipes::FramingMode::Byte,
|
||||
&named_pipes::BlockingMode::NoWait,
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
policy.set_stdout_handle(&pipe.0).unwrap();
|
||||
policy.set_stderr_handle(&pipe.0).unwrap();
|
||||
policy.add_handle_to_share(&pipe.0);
|
||||
}
|
||||
}
|
115
sandbox/src/policy.rs
Normal file
115
sandbox/src/policy.rs
Normal file
|
@ -0,0 +1,115 @@
|
|||
// Copyright 2022 The ChromiumOS Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use crate::IntegrityLevel;
|
||||
use crate::JobLevel;
|
||||
use crate::Semantics;
|
||||
use crate::SubSystem;
|
||||
use crate::TokenLevel;
|
||||
use crate::JOB_OBJECT_UILIMIT_READCLIPBOARD;
|
||||
use crate::JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
|
||||
|
||||
/// Policy struct for describing how a sandbox `TargetPolicy` should be
|
||||
/// constructed for a particular process.
|
||||
pub struct Policy {
|
||||
pub initial_token_level: TokenLevel,
|
||||
pub lockdown_token_level: TokenLevel,
|
||||
pub integrity_level: IntegrityLevel,
|
||||
pub delayed_integrity_level: IntegrityLevel,
|
||||
pub job_level: JobLevel,
|
||||
pub ui_exceptions: u32,
|
||||
pub alternate_desktop: bool,
|
||||
pub alternate_winstation: bool,
|
||||
pub exceptions: Vec<Rule>,
|
||||
pub dll_blocklist: Vec<String>,
|
||||
}
|
||||
|
||||
/// Rule struct describing a sandbox rule that should be added to the
|
||||
/// `TargetPolicy`.
|
||||
pub struct Rule {
|
||||
pub subsystem: SubSystem,
|
||||
pub semantics: Semantics,
|
||||
pub pattern: String,
|
||||
}
|
||||
|
||||
/// Policy for the main emulator process.
|
||||
pub const MAIN: Policy = Policy {
|
||||
// Token levels and integrity levels needed for access to hypervisor APIs.
|
||||
initial_token_level: TokenLevel::USER_RESTRICTED_SAME_ACCESS,
|
||||
lockdown_token_level: TokenLevel::USER_RESTRICTED_NON_ADMIN,
|
||||
integrity_level: IntegrityLevel::INTEGRITY_LEVEL_MEDIUM,
|
||||
// Needed for access to audio APIs.
|
||||
delayed_integrity_level: IntegrityLevel::INTEGRITY_LEVEL_LOW,
|
||||
// Needed for access to UI APIs.
|
||||
job_level: JobLevel::JOB_LIMITED_USER,
|
||||
ui_exceptions: JOB_OBJECT_UILIMIT_READCLIPBOARD | JOB_OBJECT_UILIMIT_WRITECLIPBOARD,
|
||||
// Needed to display window on main desktop.
|
||||
alternate_desktop: false,
|
||||
alternate_winstation: false,
|
||||
exceptions: vec![],
|
||||
dll_blocklist: vec![],
|
||||
};
|
||||
|
||||
/// Policy for the metrics process.
|
||||
pub const METRICS: Policy = Policy {
|
||||
// Needed for access to WinINet.
|
||||
initial_token_level: TokenLevel::USER_NON_ADMIN,
|
||||
lockdown_token_level: TokenLevel::USER_NON_ADMIN,
|
||||
integrity_level: IntegrityLevel::INTEGRITY_LEVEL_LOW,
|
||||
delayed_integrity_level: IntegrityLevel::INTEGRITY_LEVEL_LOW,
|
||||
job_level: JobLevel::JOB_LOCKDOWN,
|
||||
ui_exceptions: 0,
|
||||
alternate_desktop: true,
|
||||
alternate_winstation: true,
|
||||
exceptions: vec![],
|
||||
dll_blocklist: vec![],
|
||||
};
|
||||
|
||||
/// Policy for a block device process.
|
||||
pub const BLOCK: Policy = Policy {
|
||||
initial_token_level: TokenLevel::USER_RESTRICTED_NON_ADMIN,
|
||||
lockdown_token_level: TokenLevel::USER_LOCKDOWN,
|
||||
// INTEGRITY_LEVEL_MEDIUM needed to open disk file.
|
||||
integrity_level: IntegrityLevel::INTEGRITY_LEVEL_MEDIUM,
|
||||
delayed_integrity_level: IntegrityLevel::INTEGRITY_LEVEL_UNTRUSTED,
|
||||
job_level: JobLevel::JOB_LOCKDOWN,
|
||||
ui_exceptions: 0,
|
||||
alternate_desktop: true,
|
||||
alternate_winstation: true,
|
||||
exceptions: vec![],
|
||||
dll_blocklist: vec![],
|
||||
};
|
||||
|
||||
/// Policy for the network process.
|
||||
pub const NET: Policy = Policy {
|
||||
// Needed to connect to crash handler.
|
||||
initial_token_level: TokenLevel::USER_INTERACTIVE,
|
||||
lockdown_token_level: TokenLevel::USER_LOCKDOWN,
|
||||
// Process won't start below this level as loading ntdll will fail.
|
||||
integrity_level: IntegrityLevel::INTEGRITY_LEVEL_LOW,
|
||||
delayed_integrity_level: IntegrityLevel::INTEGRITY_LEVEL_UNTRUSTED,
|
||||
job_level: JobLevel::JOB_LOCKDOWN,
|
||||
ui_exceptions: 0,
|
||||
alternate_desktop: true,
|
||||
alternate_winstation: true,
|
||||
exceptions: vec![],
|
||||
dll_blocklist: vec![],
|
||||
};
|
||||
|
||||
/// Policy for the slirp process.
|
||||
pub const SLIRP: Policy = Policy {
|
||||
// Needed to connect to crash handler.
|
||||
initial_token_level: TokenLevel::USER_INTERACTIVE,
|
||||
// Needed for access to winsock.
|
||||
lockdown_token_level: TokenLevel::USER_LIMITED,
|
||||
// Needed for access to winsock.
|
||||
integrity_level: IntegrityLevel::INTEGRITY_LEVEL_LOW,
|
||||
delayed_integrity_level: IntegrityLevel::INTEGRITY_LEVEL_UNTRUSTED,
|
||||
job_level: JobLevel::JOB_LOCKDOWN,
|
||||
ui_exceptions: 0,
|
||||
alternate_desktop: true,
|
||||
alternate_winstation: true,
|
||||
exceptions: vec![],
|
||||
dll_blocklist: vec![],
|
||||
};
|
|
@ -130,6 +130,7 @@ CRATE_OPTIONS: Dict[str, List[TestOption]] = {
|
|||
],
|
||||
"libvda": [TestOption.DO_NOT_BUILD], # b/202293971
|
||||
"rutabaga_gfx": [TestOption.DO_NOT_BUILD_ARMHF], # b/210015864
|
||||
"sandbox": [TestOption.DO_NOT_RUN],
|
||||
"vhost": [TestOption.DO_NOT_RUN_ON_FOREIGN_KERNEL, TestOption.UNIT_AS_INTEGRATION_TEST],
|
||||
"vm_control": [TestOption.DO_NOT_BUILD_ARMHF], # b/210015864
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue