[go: nahoru, domu]

blob: 4151077e469b37eb8da6393911d5394769e91939 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/win/src/sandbox_policy_base.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/win/access_control_list.h"
#include "base/win/access_token.h"
#include "base/win/sid.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "sandbox/features.h"
#include "sandbox/win/src/acl.h"
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/filesystem_policy.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/named_pipe_policy.h"
#include "sandbox/win/src/policy_broker.h"
#include "sandbox/win/src/policy_engine_processor.h"
#include "sandbox/win/src/policy_low_level.h"
#include "sandbox/win/src/process_mitigations.h"
#include "sandbox/win/src/process_mitigations_win32k_policy.h"
#include "sandbox/win/src/process_thread_policy.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_policy_diagnostic.h"
#include "sandbox/win/src/signed_policy.h"
#include "sandbox/win/src/target_process.h"
#include "sandbox/win/src/top_level_dispatcher.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sandbox {
namespace {
// The standard windows size for one memory page.
constexpr size_t kOneMemPage = 4096;
// The IPC and Policy shared memory sizes.
constexpr size_t kIPCMemSize = kOneMemPage * 2;
constexpr size_t kPolMemSize = kOneMemPage * 6;
// Offset of pShimData in ntdll!_PEB.
#if defined(_WIN64)
// This is the same on x64 and arm64.
constexpr ptrdiff_t kShimDataOffset = 0x2d8;
#else
constexpr ptrdiff_t kShimDataOffset = 0x1e8;
#endif
// Helper function to allocate space (on the heap) for policy.
sandbox::PolicyGlobal* MakeBrokerPolicyMemory() {
const size_t kTotalPolicySz = kPolMemSize;
sandbox::PolicyGlobal* policy =
static_cast<sandbox::PolicyGlobal*>(::operator new(kTotalPolicySz));
DCHECK(policy);
memset(policy, 0, kTotalPolicySz);
policy->data_size = kTotalPolicySz - sizeof(sandbox::PolicyGlobal);
return policy;
}
bool IsInheritableHandle(HANDLE handle) {
if (!handle)
return false;
if (handle == INVALID_HANDLE_VALUE)
return false;
// File handles (FILE_TYPE_DISK) and pipe handles are known to be
// inheritable. Console handles (FILE_TYPE_CHAR) are not
// inheritable via PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
DWORD handle_type = GetFileType(handle);
return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE;
}
bool ReplacePackageSidInDacl(HANDLE token,
const base::win::Sid& package_sid,
ACCESS_MASK access) {
absl::optional<base::win::SecurityDescriptor> sd =
base::win::SecurityDescriptor::FromHandle(
token, base::win::SecurityObjectType::kKernel,
DACL_SECURITY_INFORMATION);
if (!sd) {
return false;
}
if (!sd->SetDaclEntry(package_sid, base::win::SecurityAccessMode::kRevoke, 0,
0) ||
!sd->SetDaclEntry(base::win::WellKnownSid::kAllApplicationPackages,
base::win::SecurityAccessMode::kGrant, access, 0)) {
return false;
}
return sd->WriteToHandle(token, base::win::SecurityObjectType::kKernel,
DACL_SECURITY_INFORMATION);
}
bool ApplyZeroAppShimToSuspendedProcess(HANDLE process) {
PROCESS_BASIC_INFORMATION proc_info{};
ULONG bytes_returned = 0;
NTSTATUS ret = GetNtExports()->QueryInformationProcess(
process, ProcessBasicInformation, &proc_info, sizeof(proc_info),
&bytes_returned);
if (!NT_SUCCESS(ret) || sizeof(proc_info) != bytes_returned) {
return false;
}
void* address = reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(proc_info.PebBaseAddress) + kShimDataOffset);
size_t zero = 0;
SIZE_T written;
if (!::WriteProcessMemory(process, const_cast<void*>(address), &zero,
sizeof(zero), &written)) {
return false;
}
if (written != sizeof(zero)) {
return false;
}
return true;
}
} // namespace
SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level =
INTEGRITY_LEVEL_LAST;
SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations = 0;
SANDBOX_INTERCEPT MitigationFlags g_shared_startup_mitigations = 0;
ConfigBase::ConfigBase() noexcept
:
#if DCHECK_IS_ON()
creating_thread_id_(GetCurrentThreadId()),
#endif // DCHECK_IS_ON()
configured_(false),
lockdown_level_(USER_LOCKDOWN),
initial_level_(USER_LOCKDOWN),
job_level_(JobLevel::kLockdown),
integrity_level_(INTEGRITY_LEVEL_LAST),
delayed_integrity_level_(INTEGRITY_LEVEL_LAST),
mitigations_(0),
delayed_mitigations_(0),
add_restricting_random_sid_(false),
lockdown_default_dacl_(false),
is_csrss_connected_(true),
memory_limit_(0),
ui_exceptions_(0),
desktop_(Desktop::kDefault),
filter_environment_(false),
zero_appshim_(false),
policy_maker_(nullptr),
policy_(nullptr) {
}
bool ConfigBase::IsOnCreatingThread() const {
#if DCHECK_IS_ON()
return GetCurrentThreadId() == creating_thread_id_;
#else // DCHECK_IS_ON()
NOTREACHED();
return true;
#endif
}
bool ConfigBase::IsConfigured() const {
return configured_;
}
bool ConfigBase::Freeze() {
DCHECK(IsOnCreatingThread());
DCHECK(!configured_);
if (policy_) {
if (!policy_maker_->Done())
return false;
// Policy maker is not needed once rules are compiled.
policy_maker_.reset();
}
configured_ = true;
return true;
}
PolicyGlobal* ConfigBase::policy() {
DCHECK(configured_);
return policy_;
}
absl::optional<base::span<const uint8_t>> ConfigBase::policy_span() {
if (policy_) {
// Note: this is not policy().data_size as that relates to internal data,
// not the entire allocated policy area.
return base::span<const uint8_t>(reinterpret_cast<uint8_t*>(policy_.get()),
kPolMemSize);
}
return absl::nullopt;
}
std::vector<std::wstring>& ConfigBase::blocklisted_dlls() {
DCHECK(configured_);
return blocklisted_dlls_;
}
AppContainerBase* ConfigBase::app_container() {
DCHECK(configured_);
return app_container_.get();
}
ConfigBase::~ConfigBase() {
// `policy_maker_` holds a raw_ptr on `policy_`, so we need to make sure it
// gets destroyed first.
policy_maker_.reset();
policy_.ClearAndDelete(); // Allocated by MakeBrokerPolicyMemory.
}
sandbox::LowLevelPolicy* ConfigBase::PolicyMaker() {
DCHECK(IsOnCreatingThread());
DCHECK(!configured_);
if (!policy_) {
policy_ = MakeBrokerPolicyMemory();
DCHECK(!policy_maker_);
policy_maker_ = std::make_unique<LowLevelPolicy>(policy_);
}
return policy_maker_.get();
}
ResultCode ConfigBase::AllowFileAccess(FileSemantics semantics,
const wchar_t* pattern) {
if (!FileSystemPolicy::GenerateRules(pattern, semantics, PolicyMaker())) {
NOTREACHED();
return SBOX_ERROR_BAD_PARAMS;
}
return SBOX_ALL_OK;
}
ResultCode ConfigBase::AllowNamedPipes(const wchar_t* pattern) {
if (!NamedPipePolicy::GenerateRules(pattern, PolicyMaker())) {
NOTREACHED();
return SBOX_ERROR_BAD_PARAMS;
}
return SBOX_ALL_OK;
}
ResultCode ConfigBase::SetFakeGdiInit() {
DCHECK_EQ(MITIGATION_WIN32K_DISABLE, mitigations_ & MITIGATION_WIN32K_DISABLE)
<< "Enable MITIGATION_WIN32K_DISABLE before adding win32k policy "
"rules.";
if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules(PolicyMaker())) {
NOTREACHED();
return SBOX_ERROR_BAD_PARAMS;
}
return SBOX_ALL_OK;
}
ResultCode ConfigBase::AllowExtraDlls(const wchar_t* pattern) {
// Signed intercept rules only supported on Windows 10 TH2 and above. This
// must match the version checks in process_mitigations.cc for
// consistency.
if (base::win::GetVersion() >= base::win::Version::WIN10_TH2) {
DCHECK_EQ(MITIGATION_FORCE_MS_SIGNED_BINS,
mitigations_ & MITIGATION_FORCE_MS_SIGNED_BINS)
<< "Enable MITIGATION_FORCE_MS_SIGNED_BINS before adding signed "
"policy rules.";
if (!SignedPolicy::GenerateRules(pattern, PolicyMaker())) {
NOTREACHED();
return SBOX_ERROR_BAD_PARAMS;
}
}
return SBOX_ALL_OK;
}
void ConfigBase::AddDllToUnload(const wchar_t* dll_name) {
blocklisted_dlls_.push_back(dll_name);
}
ResultCode ConfigBase::SetIntegrityLevel(IntegrityLevel integrity_level) {
if (app_container_)
return SBOX_ERROR_BAD_PARAMS;
integrity_level_ = integrity_level;
return SBOX_ALL_OK;
}
IntegrityLevel ConfigBase::GetIntegrityLevel() const {
return integrity_level_;
}
void ConfigBase::SetDelayedIntegrityLevel(IntegrityLevel integrity_level) {
delayed_integrity_level_ = integrity_level;
}
ResultCode ConfigBase::SetLowBox(const wchar_t* sid) {
if (!features::IsAppContainerSandboxSupported())
return SBOX_ERROR_UNSUPPORTED;
DCHECK(sid);
if (app_container_)
return SBOX_ERROR_BAD_PARAMS;
app_container_ = AppContainerBase::CreateLowbox(sid);
if (!app_container_)
return SBOX_ERROR_INVALID_LOWBOX_SID;
return SBOX_ALL_OK;
}
ResultCode ConfigBase::SetProcessMitigations(MitigationFlags flags) {
// Prior to Win10 RS5 CreateProcess fails when AppContainer and mitigation
// flags are enabled. Return an error on downlevel platforms if trying to
// set new mitigations.
if (app_container_ &&
base::win::GetVersion() < base::win::Version::WIN10_RS5) {
return SBOX_ERROR_BAD_PARAMS;
}
if (!CanSetProcessMitigationsPreStartup(flags))
return SBOX_ERROR_BAD_PARAMS;
mitigations_ = flags;
return SBOX_ALL_OK;
}
MitigationFlags ConfigBase::GetProcessMitigations() {
return mitigations_;
}
ResultCode ConfigBase::SetDelayedProcessMitigations(MitigationFlags flags) {
if (!CanSetProcessMitigationsPostStartup(flags))
return SBOX_ERROR_BAD_PARAMS;
delayed_mitigations_ = flags;
return SBOX_ALL_OK;
}
MitigationFlags ConfigBase::GetDelayedProcessMitigations() const {
return delayed_mitigations_;
}
void ConfigBase::AddRestrictingRandomSid() {
add_restricting_random_sid_ = true;
}
void ConfigBase::SetLockdownDefaultDacl() {
lockdown_default_dacl_ = true;
}
ResultCode ConfigBase::AddAppContainerProfile(const wchar_t* package_name,
bool create_profile) {
if (!features::IsAppContainerSandboxSupported())
return SBOX_ERROR_UNSUPPORTED;
DCHECK(!configured_);
DCHECK(package_name);
if (app_container_ || integrity_level_ != INTEGRITY_LEVEL_LAST) {
return SBOX_ERROR_BAD_PARAMS;
}
if (create_profile) {
app_container_ = AppContainerBase::CreateProfile(
package_name, L"Chrome Sandbox", L"Profile for Chrome Sandbox");
} else {
app_container_ = AppContainerBase::Open(package_name);
}
if (!app_container_)
return SBOX_ERROR_CREATE_APPCONTAINER;
// A bug exists in CreateProcess where enabling an AppContainer profile and
// passing a set of mitigation flags will generate ERROR_INVALID_PARAMETER.
// Apply best efforts here and convert set mitigations to delayed mitigations.
// This bug looks to have been fixed in Win10 RS5, so exit early if possible.
if (base::win::GetVersion() >= base::win::Version::WIN10_RS5)
return SBOX_ALL_OK;
delayed_mitigations_ =
mitigations_ & GetAllowedPostStartupProcessMitigations();
DCHECK(delayed_mitigations_ ==
(mitigations_ & ~(MITIGATION_SEHOP |
MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION)));
mitigations_ = 0;
return SBOX_ALL_OK;
}
scoped_refptr<AppContainer> ConfigBase::GetAppContainer() {
return app_container_;
}
ResultCode ConfigBase::SetTokenLevel(TokenLevel initial, TokenLevel lockdown) {
// Note: TokenLevel enum values increase as lockdown decreases.
if (initial < lockdown) {
return SBOX_ERROR_BAD_PARAMS;
}
initial_level_ = initial;
lockdown_level_ = lockdown;
return SBOX_ALL_OK;
}
TokenLevel ConfigBase::GetInitialTokenLevel() const {
return initial_level_;
}
TokenLevel ConfigBase::GetLockdownTokenLevel() const {
return lockdown_level_;
}
ResultCode ConfigBase::SetJobLevel(JobLevel job_level, uint32_t ui_exceptions) {
job_level_ = job_level;
ui_exceptions_ = ui_exceptions;
return SBOX_ALL_OK;
}
JobLevel ConfigBase::GetJobLevel() const {
return job_level_;
}
void ConfigBase::SetJobMemoryLimit(size_t memory_limit) {
memory_limit_ = memory_limit;
}
ResultCode ConfigBase::AddKernelObjectToClose(const wchar_t* handle_type,
const wchar_t* handle_name) {
DCHECK(!configured_);
if (!handle_closer_)
handle_closer_ = std::make_unique<HandleCloser>();
return handle_closer_->AddHandle(handle_type, handle_name);
}
ResultCode ConfigBase::SetDisconnectCsrss() {
// Does not work on 32-bit, and the ASAN runtime falls over with the
// CreateThread EAT patch used when this is enabled.
// See https://crbug.com/783296#c27.
#if defined(_WIN64) && !defined(ADDRESS_SANITIZER)
is_csrss_connected_ = false;
return AddKernelObjectToClose(L"ALPC Port", nullptr);
#else
return SBOX_ALL_OK;
#endif // !defined(_WIN64) || defined(ADDRESS_SANITIZER)
}
void ConfigBase::SetDesktop(Desktop desktop) {
desktop_ = desktop;
}
void ConfigBase::SetFilterEnvironment(bool filter) {
filter_environment_ = filter;
}
bool ConfigBase::GetEnvironmentFiltered() {
return filter_environment_;
}
void ConfigBase::SetZeroAppShim() {
zero_appshim_ = true;
}
PolicyBase::PolicyBase(base::StringPiece tag)
: tag_(tag),
config_(),
config_ptr_(nullptr),
stdout_handle_(INVALID_HANDLE_VALUE),
stderr_handle_(INVALID_HANDLE_VALUE),
delegate_data_(nullptr),
job_() {
dispatcher_ = std::make_unique<TopLevelDispatcher>(this);
}
PolicyBase::~PolicyBase() {
// Ensure this is cleared before other members - this terminates the process
// if it hasn't already finished.
target_.reset();
}
TargetConfig* PolicyBase::GetConfig() {
return config();
}
ConfigBase* PolicyBase::config() {
if (config_ptr_) {
DCHECK(!config_);
// Should have a tag if we are sharing backing configuration.
DCHECK(!tag_.empty());
return config_ptr_;
}
if (!config_) {
DCHECK(tag_.empty());
config_ = std::make_unique<ConfigBase>();
}
return config_.get();
}
bool PolicyBase::SetConfig(TargetConfig* config) {
// Cannot call this method if we already own our memory.
DCHECK(!config_);
// Cannot call this method twice.
DCHECK(!config_ptr_);
// Must provide valid shared data region.
DCHECK(config);
// Should have a tag.
DCHECK(!tag_.empty());
config_ptr_ = static_cast<ConfigBase*>(config);
return true;
}
ResultCode PolicyBase::SetStdoutHandle(HANDLE handle) {
if (!IsInheritableHandle(handle))
return SBOX_ERROR_BAD_PARAMS;
stdout_handle_ = handle;
return SBOX_ALL_OK;
}
ResultCode PolicyBase::SetStderrHandle(HANDLE handle) {
if (!IsInheritableHandle(handle))
return SBOX_ERROR_BAD_PARAMS;
stderr_handle_ = handle;
return SBOX_ALL_OK;
}
void PolicyBase::AddHandleToShare(HANDLE handle) {
CHECK(handle);
CHECK_NE(handle, INVALID_HANDLE_VALUE);
// Ensure the handle can be inherited.
bool result =
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
PCHECK(result);
handles_to_share_.push_back(handle);
}
const base::HandlesToInheritVector& PolicyBase::GetHandlesBeingShared() {
return handles_to_share_;
}
ResultCode PolicyBase::InitJob() {
if (job_.IsValid())
return SBOX_ERROR_BAD_PARAMS;
// Create the Windows job object.
DWORD result = job_.Init(config()->GetJobLevel(), config()->ui_exceptions(),
config()->memory_limit());
if (ERROR_SUCCESS != result)
return SBOX_ERROR_CANNOT_INIT_JOB;
return SBOX_ALL_OK;
}
HANDLE PolicyBase::GetJobHandle() {
return job_.GetHandle();
}
bool PolicyBase::HasJob() {
return job_.IsValid();
}
ResultCode PolicyBase::DropActiveProcessLimit() {
if (!job_.IsValid())
return SBOX_ERROR_BAD_PARAMS;
if (config()->GetJobLevel() >= JobLevel::kInteractive)
return SBOX_ALL_OK;
if (ERROR_SUCCESS != job_.SetActiveProcessLimit(0))
return SBOX_ERROR_CANNOT_UPDATE_JOB_PROCESS_LIMIT;
return SBOX_ALL_OK;
}
ResultCode PolicyBase::MakeTokens(
absl::optional<base::win::AccessToken>& initial,
absl::optional<base::win::AccessToken>& lockdown) {
absl::optional<base::win::Sid> random_sid;
if (config()->add_restricting_random_sid()) {
random_sid = base::win::Sid::GenerateRandomSid();
}
IntegrityLevel integrity_level = config()->integrity_level();
bool lockdown_default_dacl = config()->lockdown_default_dacl();
// Create the 'naked' token. This will be the permanent token associated
// with the process and therefore with any thread that is not impersonating.
absl::optional<base::win::AccessToken> primary = CreateRestrictedToken(
config()->GetLockdownTokenLevel(), integrity_level, TokenType::kPrimary,
lockdown_default_dacl, random_sid);
if (!primary) {
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_TOKEN;
}
AppContainerBase* app_container = config()->app_container();
if (app_container &&
app_container->GetAppContainerType() == AppContainerType::kLowbox) {
// Build the lowbox lockdown (primary) token.
primary = app_container->BuildPrimaryToken(*primary);
if (!primary) {
return SBOX_ERROR_CANNOT_CREATE_LOWBOX_TOKEN;
}
if (!ReplacePackageSidInDacl(primary->get(), app_container->GetPackageSid(),
TOKEN_ALL_ACCESS)) {
return SBOX_ERROR_CANNOT_MODIFY_LOWBOX_TOKEN_DACL;
}
}
lockdown = std::move(*primary);
// Create the 'better' token. We use this token as the one that the main
// thread uses when booting up the process. It should contain most of
// what we need (before reaching main( ))
absl::optional<base::win::AccessToken> impersonation = CreateRestrictedToken(
config()->GetInitialTokenLevel(), integrity_level,
TokenType::kImpersonation, lockdown_default_dacl, random_sid);
if (!impersonation) {
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_IMP_TOKEN;
}
if (app_container) {
impersonation = app_container->BuildImpersonationToken(*impersonation);
if (!impersonation) {
return SBOX_ERROR_CANNOT_CREATE_LOWBOX_IMPERSONATION_TOKEN;
}
}
initial = std::move(*impersonation);
return SBOX_ALL_OK;
}
ResultCode PolicyBase::ApplyToTarget(std::unique_ptr<TargetProcess> target) {
if (target_)
return SBOX_ERROR_UNEXPECTED_CALL;
// Policy rules are compiled when the underlying ConfigBase is frozen.
DCHECK(config()->IsConfigured());
if (config()->zero_appshim()) {
if (!ApplyZeroAppShimToSuspendedProcess(target->Process())) {
return SBOX_ERROR_DISABLING_APPHELP;
}
}
if (!ApplyProcessMitigationsToSuspendedProcess(
target->Process(), config()->GetProcessMitigations())) {
return SBOX_ERROR_APPLY_ASLR_MITIGATIONS;
}
ResultCode ret = SetupAllInterceptions(*target);
if (ret != SBOX_ALL_OK)
return ret;
if (!SetupHandleCloser(*target))
return SBOX_ERROR_SETUP_HANDLE_CLOSER;
DWORD win_error = ERROR_SUCCESS;
// Initialize the sandbox infrastructure for the target.
// TODO(wfh) do something with win_error code here.
ret = target->Init(dispatcher_.get(), config()->policy_span(),
delegate_data_span(), kIPCMemSize, &win_error);
if (ret != SBOX_ALL_OK)
return ret;
g_shared_delayed_integrity_level = config()->delayed_integrity_level();
ret = target->TransferVariable("g_shared_delayed_integrity_level",
&g_shared_delayed_integrity_level,
sizeof(g_shared_delayed_integrity_level));
g_shared_delayed_integrity_level = INTEGRITY_LEVEL_LAST;
if (SBOX_ALL_OK != ret)
return ret;
// Add in delayed mitigations and pseudo-mitigations enforced at startup.
g_shared_delayed_mitigations =
config()->GetDelayedProcessMitigations() |
FilterPostStartupProcessMitigations(config()->GetProcessMitigations());
if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations))
return SBOX_ERROR_BAD_PARAMS;
ret = target->TransferVariable("g_shared_delayed_mitigations",
&g_shared_delayed_mitigations,
sizeof(g_shared_delayed_mitigations));
g_shared_delayed_mitigations = 0;
if (SBOX_ALL_OK != ret)
return ret;
g_shared_startup_mitigations = config()->GetProcessMitigations();
ret = target->TransferVariable("g_shared_startup_mitigations",
&g_shared_startup_mitigations,
sizeof(g_shared_startup_mitigations));
g_shared_startup_mitigations = 0;
if (SBOX_ALL_OK != ret)
return ret;
target_ = std::move(target);
return SBOX_ALL_OK;
}
EvalResult PolicyBase::EvalPolicy(IpcTag service,
CountedParameterSetBase* params) {
PolicyGlobal* policy = config()->policy();
if (policy) {
if (!policy->entry[static_cast<size_t>(service)]) {
// There is no policy for this particular service. This is not a big
// deal.
return DENY_ACCESS;
}
for (size_t i = 0; i < params->count; i++) {
if (!params->parameters[i].IsValid()) {
NOTREACHED();
return SIGNAL_ALARM;
}
}
PolicyProcessor pol_evaluator(policy->entry[static_cast<size_t>(service)]);
PolicyResult result =
pol_evaluator.Evaluate(kShortEval, params->parameters, params->count);
if (POLICY_MATCH == result)
return pol_evaluator.GetAction();
DCHECK(POLICY_ERROR != result);
}
return DENY_ACCESS;
}
HANDLE PolicyBase::GetStdoutHandle() {
return stdout_handle_;
}
HANDLE PolicyBase::GetStderrHandle() {
return stderr_handle_;
}
ResultCode PolicyBase::SetupAllInterceptions(TargetProcess& target) {
InterceptionManager manager(target);
PolicyGlobal* policy = config()->policy();
if (policy) {
for (size_t i = 0; i < kMaxIpcTag; i++) {
if (policy->entry[i] &&
!dispatcher_->SetupService(&manager, static_cast<IpcTag>(i)))
return SBOX_ERROR_SETUP_INTERCEPTION_SERVICE;
}
}
for (const std::wstring& dll : config()->blocklisted_dlls())
manager.AddToUnloadModules(dll.c_str());
if (!SetupBasicInterceptions(&manager, config()->is_csrss_connected()))
return SBOX_ERROR_SETUP_BASIC_INTERCEPTIONS;
ResultCode rc = manager.InitializeInterceptions();
if (rc != SBOX_ALL_OK)
return rc;
// Finally, setup imports on the target so the interceptions can work.
if (!SetupNtdllImports(target))
return SBOX_ERROR_SETUP_NTDLL_IMPORTS;
return SBOX_ALL_OK;
}
bool PolicyBase::SetupHandleCloser(TargetProcess& target) {
auto* handle_closer = config()->handle_closer();
if (!handle_closer)
return true;
return handle_closer->InitializeTargetHandles(target);
}
absl::optional<base::span<const uint8_t>> PolicyBase::delegate_data_span() {
if (delegate_data_) {
return base::make_span(*delegate_data_);
}
return absl::nullopt;
}
void PolicyBase::AddDelegateData(base::span<const uint8_t> data) {
CHECK(data.size() > 0u);
// Can only set this once - as there is only one region sent to the child.
CHECK(!delegate_data_);
delegate_data_ =
std::make_unique<std::vector<const uint8_t>>(data.begin(), data.end());
}
} // namespace sandbox