Commit a415b3bf authored by Will Harris's avatar Will Harris Committed by Commit Bot

Reland "Reland "Sandbox: Add support for CIG pre-launch.""

This is a reland of 7d5fe940

Original change's description:
> Reland "Sandbox: Add support for CIG pre-launch."
> 
> This is a reland of 9e89ae37
> 
> Original change's description:
> > Sandbox: Add support for CIG pre-launch.
> > 
> > This CL allows MITIGATION_FORCE_MS_SIGNED_BINS to be
> > enabled pre-launch for targets even with dependent DLLs
> > It achieves this by adding a sandbox intercept for
> > NtCreateSection and permitting sections backing modules
> > that match a whitelist to be created in the broker
> > and mapped into the target for the load to succeed.
> > 
> > BUG=750886
> > 
> > Change-Id: Iac22e206f77f99d9c2253e906780f1bcf5e8e3e6
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1660097
> > Commit-Queue: Will Harris <wfh@chromium.org>
> > Reviewed-by: James Forshaw <forshaw@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#676665}
> 
> Bug: 750886
> Change-Id: I0de3189df0e5435fb33717fcaa3f82768d4504f6
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1699271
> Reviewed-by: James Forshaw <forshaw@chromium.org>
> Commit-Queue: Will Harris <wfh@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#677510}

Bug: 750886
Change-Id: Ib77c5590e58c395d8cedef12be46896919c457ab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1709798Reviewed-by: default avatarJames Forshaw <forshaw@chromium.org>
Reviewed-by: default avatarReid Kleckner <rnk@chromium.org>
Commit-Queue: Will Harris <wfh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#679813}
parent 225514ae
...@@ -118,6 +118,12 @@ static_library("sandbox") { ...@@ -118,6 +118,12 @@ static_library("sandbox") {
"src/sharedmem_ipc_server.h", "src/sharedmem_ipc_server.h",
"src/sid.cc", "src/sid.cc",
"src/sid.h", "src/sid.h",
"src/signed_dispatcher.cc",
"src/signed_dispatcher.h",
"src/signed_interception.cc",
"src/signed_interception.h",
"src/signed_policy.cc",
"src/signed_policy.h",
"src/sync_dispatcher.cc", "src/sync_dispatcher.cc",
"src/sync_dispatcher.h", "src/sync_dispatcher.h",
"src/sync_interception.cc", "src/sync_interception.cc",
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define SANDBOX_FUZZER_TYPES_H_ #define SANDBOX_FUZZER_TYPES_H_
#include <stdint.h> #include <stdint.h>
#include <string.h>
// This file defines Windows types for the sandbox_ipc_fuzzer target when // This file defines Windows types for the sandbox_ipc_fuzzer target when
// compiled on Linux. // compiled on Linux.
...@@ -35,4 +36,12 @@ typedef void PROCESS_INFORMATION; ...@@ -35,4 +36,12 @@ typedef void PROCESS_INFORMATION;
// __stdcall is used in one place. TODO(wfh): replace with WINAPI. // __stdcall is used in one place. TODO(wfh): replace with WINAPI.
#define __stdcall #define __stdcall
namespace sandbox {
struct NtExports {
using memcpyFunction = decltype(&memcpy);
memcpyFunction memcpy;
};
} // namespace sandbox
#endif // SANDBOX_FUZZER_TYPES_H_ #endif // SANDBOX_FUZZER_TYPES_H_
...@@ -224,7 +224,7 @@ class CopyHelper<InOutCountedBuffer> { ...@@ -224,7 +224,7 @@ class CopyHelper<InOutCountedBuffer> {
// We are touching user memory, this has to be done from inside a try // We are touching user memory, this has to be done from inside a try
// except. // except.
__try { __try {
memcpy(t_.Buffer(), buffer, t_.Size()); memcpy_wrapper(t_.Buffer(), buffer, t_.Size());
} __except (EXCEPTION_EXECUTE_HANDLER) { } __except (EXCEPTION_EXECUTE_HANDLER) {
return false; return false;
} }
......
...@@ -20,15 +20,11 @@ ...@@ -20,15 +20,11 @@
#include "base/macros.h" #include "base/macros.h"
#include "sandbox/win/src/internal_types.h" #include "sandbox/win/src/internal_types.h"
#if !defined(SANDBOX_FUZZ_TARGET)
#include "sandbox/win/src/sandbox_nt_types.h"
#endif
#include "sandbox/win/src/sandbox_types.h" #include "sandbox/win/src/sandbox_types.h"
// Increases |value| until there is no need for padding given an int64_t
// alignment. Returns the increased value.
inline uint32_t Align(uint32_t value) {
uint32_t alignment = sizeof(int64_t);
return ((value + alignment - 1) / alignment) * alignment;
}
// This header is part of CrossCall: the sandbox inter-process communication. // This header is part of CrossCall: the sandbox inter-process communication.
// This header defines the basic types used both in the client IPC and in the // This header defines the basic types used both in the client IPC and in the
// server IPC code. CrossCallParams and ActualCallParams model the input // server IPC code. CrossCallParams and ActualCallParams model the input
...@@ -49,6 +45,26 @@ inline uint32_t Align(uint32_t value) { ...@@ -49,6 +45,26 @@ inline uint32_t Align(uint32_t value) {
namespace sandbox { namespace sandbox {
// This is the list of all imported symbols from ntdll.dll.
SANDBOX_INTERCEPT NtExports g_nt;
namespace {
// Increases |value| until there is no need for padding given an int64_t
// alignment. Returns the increased value.
inline uint32_t Align(uint32_t value) {
uint32_t alignment = sizeof(int64_t);
return ((value + alignment - 1) / alignment) * alignment;
}
inline void* memcpy_wrapper(void* dest, const void* src, size_t count) {
if (g_nt.memcpy)
return g_nt.memcpy(dest, src, count);
return memcpy(dest, src, count);
}
} // namespace
// max number of extended return parameters. See CrossCallReturn // max number of extended return parameters. See CrossCallReturn
const size_t kExtendedReturnCount = 8; const size_t kExtendedReturnCount = 8;
...@@ -243,7 +259,7 @@ class ActualCallParams : public CrossCallParams { ...@@ -243,7 +259,7 @@ class ActualCallParams : public CrossCallParams {
// We might be touching user memory, this has to be done from inside a try // We might be touching user memory, this has to be done from inside a try
// except. // except.
__try { __try {
memcpy(dest, parameter_address, size); memcpy_wrapper(dest, parameter_address, size);
} __except (EXCEPTION_EXECUTE_HANDLER) { } __except (EXCEPTION_EXECUTE_HANDLER) {
return false; return false;
} }
......
...@@ -61,6 +61,8 @@ enum InterceptorId { ...@@ -61,6 +61,8 @@ enum InterceptorId {
GETOPMRANDOMNUMBER_ID, GETOPMRANDOMNUMBER_ID,
GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_ID, GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_ID,
SETOPMSIGNINGKEYANDSEQUENCENUMBERS_ID, SETOPMSIGNINGKEYANDSEQUENCENUMBERS_ID,
// Signed dispatcher:
CREATE_SECTION_ID,
INTERCEPTOR_MAX_ID INTERCEPTOR_MAX_ID
}; };
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "sandbox/win/src/registry_interception.h" #include "sandbox/win/src/registry_interception.h"
#include "sandbox/win/src/sandbox_nt_types.h" #include "sandbox/win/src/sandbox_nt_types.h"
#include "sandbox/win/src/sandbox_types.h" #include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/signed_interception.h"
#include "sandbox/win/src/sync_interception.h" #include "sandbox/win/src/sync_interception.h"
#include "sandbox/win/src/target_interceptions.h" #include "sandbox/win/src/target_interceptions.h"
...@@ -512,4 +513,19 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetConfigureOPMProtectedOutput64( ...@@ -512,4 +513,19 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetConfigureOPMProtectedOutput64(
additional_parameters); additional_parameters);
} }
SANDBOX_INTERCEPT NTSTATUS WINAPI
TargetNtCreateSection64(PHANDLE section_handle,
ACCESS_MASK desired_access,
POBJECT_ATTRIBUTES object_attributes,
PLARGE_INTEGER maximum_size,
ULONG section_page_protection,
ULONG allocation_attributes,
HANDLE file_handle) {
NtCreateSectionFunction orig_fn =
reinterpret_cast<NtCreateSectionFunction>(g_originals[CREATE_SECTION_ID]);
return TargetNtCreateSection(
orig_fn, section_handle, desired_access, object_attributes, maximum_size,
section_page_protection, allocation_attributes, file_handle);
}
} // namespace sandbox } // namespace sandbox
...@@ -310,6 +310,19 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetConfigureOPMProtectedOutput64( ...@@ -310,6 +310,19 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetConfigureOPMProtectedOutput64(
ULONG additional_parameters_size, ULONG additional_parameters_size,
const BYTE* additional_parameters); const BYTE* additional_parameters);
// -----------------------------------------------------------------------
// Interceptors handled by the signed process code.
// Interception of NtCreateSection on the child process.
SANDBOX_INTERCEPT NTSTATUS WINAPI
TargetNtCreateSection64(PHANDLE section_handle,
ACCESS_MASK desired_access,
POBJECT_ATTRIBUTES object_attributes,
PLARGE_INTEGER maximum_size,
ULONG section_page_protection,
ULONG allocation_attributes,
HANDLE file_handle);
} // extern "C" } // extern "C"
} // namespace sandbox } // namespace sandbox
......
...@@ -44,6 +44,7 @@ enum { ...@@ -44,6 +44,7 @@ enum {
IPC_GDI_GETOPMRANDOMNUMBER_TAG, IPC_GDI_GETOPMRANDOMNUMBER_TAG,
IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG, IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG,
IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG, IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG,
IPC_NTCREATESECTION_TAG,
IPC_LAST_TAG IPC_LAST_TAG
}; };
......
...@@ -35,6 +35,7 @@ typedef LONG NTSTATUS; ...@@ -35,6 +35,7 @@ typedef LONG NTSTATUS;
#define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL) #define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL)
#define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL) #define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL)
#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL) #define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL)
#define STATUS_INVALID_IMAGE_HASH ((NTSTATUS)0xC0000428L)
// clang-format on // clang-format on
#define CURRENT_PROCESS ((HANDLE)-1) #define CURRENT_PROCESS ((HANDLE)-1)
......
...@@ -82,15 +82,24 @@ void TestWin10NonSystemFont(bool is_success_test) { ...@@ -82,15 +82,24 @@ void TestWin10NonSystemFont(bool is_success_test) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void TestWin10MsSigned(bool expect_success, void TestWin10MsSigned(bool expect_success,
bool enable_mitigation, bool enable_mitigation,
bool use_ms_signed_binary) { bool delayed,
bool use_ms_signed_binary,
bool add_dll_permission,
bool add_directory_permission) {
sandbox::TestRunner runner; sandbox::TestRunner runner;
sandbox::TargetPolicy* policy = runner.GetPolicy(); sandbox::TargetPolicy* policy = runner.GetPolicy();
if (enable_mitigation) { if (enable_mitigation) {
// Enable the ForceMsSigned mitigation. // Enable the ForceMsSigned mitigation.
EXPECT_EQ(policy->SetDelayedProcessMitigations( if (delayed) {
sandbox::MITIGATION_FORCE_MS_SIGNED_BINS), EXPECT_EQ(policy->SetDelayedProcessMitigations(
sandbox::SBOX_ALL_OK); sandbox::MITIGATION_FORCE_MS_SIGNED_BINS),
sandbox::SBOX_ALL_OK);
} else {
EXPECT_EQ(policy->SetProcessMitigations(
sandbox::MITIGATION_FORCE_MS_SIGNED_BINS),
sandbox::SBOX_ALL_OK);
}
} }
// Choose the appropriate DLL and make sure the sandbox allows access to it. // Choose the appropriate DLL and make sure the sandbox allows access to it.
...@@ -101,10 +110,25 @@ void TestWin10MsSigned(bool expect_success, ...@@ -101,10 +110,25 @@ void TestWin10MsSigned(bool expect_success,
} else { } else {
EXPECT_TRUE(base::PathService::Get(base::DIR_EXE, &dll_path)); EXPECT_TRUE(base::PathService::Get(base::DIR_EXE, &dll_path));
dll_path = dll_path.Append(hooking_dll::g_hook_dll_file); dll_path = dll_path.Append(hooking_dll::g_hook_dll_file);
if (add_dll_permission) {
EXPECT_EQ(sandbox::SBOX_ALL_OK,
policy->AddRule(sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY,
sandbox::TargetPolicy::SIGNED_ALLOW_LOAD,
dll_path.value().c_str()));
}
if (add_directory_permission) {
base::FilePath exe_path;
EXPECT_TRUE(base::PathService::Get(base::DIR_EXE, &exe_path));
EXPECT_EQ(sandbox::SBOX_ALL_OK,
policy->AddRule(
sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY,
sandbox::TargetPolicy::SIGNED_ALLOW_LOAD,
exe_path.DirName().AppendASCII("*.dll").value().c_str()));
}
} }
EXPECT_TRUE(runner.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_READONLY, EXPECT_TRUE(runner.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_READONLY,
dll_path.value().c_str())); dll_path.value().c_str()));
// Set up test string. // Set up test string.
base::string16 test = L"TestDllLoad \""; base::string16 test = L"TestDllLoad \"";
test += dll_path.value().c_str(); test += dll_path.value().c_str();
...@@ -711,7 +735,7 @@ TEST(ProcessMitigationsTest, CheckWin10NonSystemFontLockDownLoadFailure) { ...@@ -711,7 +735,7 @@ TEST(ProcessMitigationsTest, CheckWin10NonSystemFontLockDownLoadFailure) {
// This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS // This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS
// mitigation enables the setting on a process. // mitigation enables the setting on a process.
TEST(ProcessMitigationsTest, CheckWin10MsSignedPolicySuccess) { TEST(ProcessMitigationsTest, CheckWin10MsSignedPolicySuccessDelayed) {
if (base::win::GetVersion() < base::win::Version::WIN10_TH2) if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
return; return;
...@@ -736,6 +760,41 @@ TEST(ProcessMitigationsTest, CheckWin10MsSignedPolicySuccess) { ...@@ -736,6 +760,41 @@ TEST(ProcessMitigationsTest, CheckWin10MsSignedPolicySuccess) {
#endif // !defined(COMPONENT_BUILD) #endif // !defined(COMPONENT_BUILD)
} }
// This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS
// mitigation enables the setting on a process when non-delayed.
TEST(ProcessMitigationsTest, CheckWin10MsSignedPolicySuccess) {
if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
return;
base::string16 test_command = L"CheckPolicy ";
test_command += std::to_wstring(TESTPOLICY_MSSIGNED);
//---------------------------------
// 1) Test setting post-startup.
// **Only test if NOT component build, otherwise component DLLs are not signed
// by MS and prevent process setup.
// **Only test post-startup, otherwise this test executable has dependencies
// on DLLs that are not signed by MS and they prevent process startup.
//---------------------------------
TestRunner runner2;
sandbox::TargetPolicy* policy = runner2.GetPolicy();
EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_FORCE_MS_SIGNED_BINS),
SBOX_ALL_OK);
// In a component build, the DLLs must be allowed to load.
#if defined(COMPONENT_BUILD)
base::FilePath exe_path;
EXPECT_TRUE(base::PathService::Get(base::DIR_EXE, &exe_path));
// Allow all *.dll in current directory to load.
EXPECT_EQ(
sandbox::SBOX_ALL_OK,
policy->AddRule(sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY,
sandbox::TargetPolicy::SIGNED_ALLOW_LOAD,
exe_path.DirName().AppendASCII("*.dll").value().c_str()));
#endif // defined(COMPONENT_BUILD)
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
}
// This test validates that we can load an unsigned DLL if the // This test validates that we can load an unsigned DLL if the
// MITIGATION_FORCE_MS_SIGNED_BINS mitigation is NOT set. // MITIGATION_FORCE_MS_SIGNED_BINS mitigation is NOT set.
TEST(ProcessMitigationsTest, CheckWin10MsSigned_Success) { TEST(ProcessMitigationsTest, CheckWin10MsSigned_Success) {
...@@ -746,7 +805,10 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_Success) { ...@@ -746,7 +805,10 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_Success) {
TestWin10MsSigned(true /* expect_success */, TestWin10MsSigned(true /* expect_success */,
false /* enable_mitigation */, false /* enable_mitigation */,
false /* use_ms_signed_binary */); false /* delayed */,
false /* use_ms_signed_binary */,
false /* add_dll_permission */,
false /* add_directory_permission */);
} }
// This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS // This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS
...@@ -759,7 +821,37 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_Failure) { ...@@ -759,7 +821,37 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_Failure) {
TestWin10MsSigned(false /* expect_success */, TestWin10MsSigned(false /* expect_success */,
true /* enable_mitigation */, true /* enable_mitigation */,
false /* use_ms_signed_binary */); true /* delayed */,
false /* use_ms_signed_binary */,
false /* add_dll_permission */,
false /* add_directory_permission */);
}
// This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS
// mitigation allows the loading of an unsigned DLL if intercept in place.
TEST(ProcessMitigationsTest, CheckWin10MsSignedWithIntercept_Success) {
if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
return;
ScopedTestMutex mutex(hooking_dll::g_hooking_dll_mutex);
// Expect success; Enable mitigation; Use non MS-signed binary.
#if defined(COMPONENT_BUILD)
// In a component build, add the directory to the allowed list.
TestWin10MsSigned(true /* expect_success */,
true /* enable_mitigation */,
false /* delayed */,
false /* use_ms_signed_binary */,
true /* add_dll_permission */,
true /* add_directory_permission */);
#else
TestWin10MsSigned(true /* expect_success */,
true /* enable_mitigation */,
false /* delayed */,
false /* use_ms_signed_binary */,
true /* add_dll_permission */,
false /* add_directory_permission */);
#endif // defined(COMPONENT_BUILD)
} }
// This test validates that we can load a signed Microsoft DLL if the // This test validates that we can load a signed Microsoft DLL if the
...@@ -773,7 +865,10 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_MsBaseline) { ...@@ -773,7 +865,10 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_MsBaseline) {
TestWin10MsSigned(true /* expect_success */, TestWin10MsSigned(true /* expect_success */,
false /* enable_mitigation */, false /* enable_mitigation */,
true /* use_ms_signed_binary */); false /* delayed */,
true /* use_ms_signed_binary */,
false /* add_dll_permission */,
false /* add_directory_permission */);
} }
// This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS // This test validates that setting the MITIGATION_FORCE_MS_SIGNED_BINS
...@@ -786,7 +881,10 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_MsSuccess) { ...@@ -786,7 +881,10 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_MsSuccess) {
TestWin10MsSigned(true /* expect_success */, TestWin10MsSigned(true /* expect_success */,
true /* enable_mitigation */, true /* enable_mitigation */,
true /* use_ms_signed_binary */); true /* delayed */,
true /* use_ms_signed_binary */,
false /* add_dll_permission */,
false /* add_directory_permission */);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
......
...@@ -24,12 +24,13 @@ class TargetPolicy { ...@@ -24,12 +24,13 @@ class TargetPolicy {
// exactly like the CreateProcess API does. See the comment at the top of // exactly like the CreateProcess API does. See the comment at the top of
// process_thread_dispatcher.cc for more details. // process_thread_dispatcher.cc for more details.
enum SubSystem { enum SubSystem {
SUBSYS_FILES, // Creation and opening of files and pipes. SUBSYS_FILES, // Creation and opening of files and pipes.
SUBSYS_NAMED_PIPES, // Creation of named pipes. SUBSYS_NAMED_PIPES, // Creation of named pipes.
SUBSYS_PROCESS, // Creation of child processes. SUBSYS_PROCESS, // Creation of child processes.
SUBSYS_REGISTRY, // Creation and opening of registry keys. SUBSYS_REGISTRY, // Creation and opening of registry keys.
SUBSYS_SYNC, // Creation of named sync objects. SUBSYS_SYNC, // Creation of named sync objects.
SUBSYS_WIN32K_LOCKDOWN // Win32K Lockdown related policy. SUBSYS_WIN32K_LOCKDOWN, // Win32K Lockdown related policy.
SUBSYS_SIGNED_BINARY // Signed binary policy.
}; };
// Allowable semantics when a rule is matched. // Allowable semantics when a rule is matched.
...@@ -56,9 +57,10 @@ class TargetPolicy { ...@@ -56,9 +57,10 @@ class TargetPolicy {
FAKE_USER_GDI_INIT, // Fakes user32 and gdi32 initialization. This can FAKE_USER_GDI_INIT, // Fakes user32 and gdi32 initialization. This can
// be used to allow the DLLs to load and initialize // be used to allow the DLLs to load and initialize
// even if the process cannot access that subsystem. // even if the process cannot access that subsystem.
IMPLEMENT_OPM_APIS // Implements FAKE_USER_GDI_INIT and also exposes IMPLEMENT_OPM_APIS, // Implements FAKE_USER_GDI_INIT and also exposes
// IPC calls to handle Output Protection Manager // IPC calls to handle Output Protection Manager
// APIs. // APIs.
SIGNED_ALLOW_LOAD // Allows loading the module when CIG is enabled.
}; };
// Increments the reference count of this object. The reference count must // Increments the reference count of this object. The reference count must
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "sandbox/win/src/sandbox_policy.h" #include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_utils.h" #include "sandbox/win/src/sandbox_utils.h"
#include "sandbox/win/src/security_capabilities.h" #include "sandbox/win/src/security_capabilities.h"
#include "sandbox/win/src/signed_policy.h"
#include "sandbox/win/src/sync_policy.h" #include "sandbox/win/src/sync_policy.h"
#include "sandbox/win/src/target_process.h" #include "sandbox/win/src/target_process.h"
#include "sandbox/win/src/top_level_dispatcher.h" #include "sandbox/win/src/top_level_dispatcher.h"
...@@ -745,6 +746,17 @@ ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem, ...@@ -745,6 +746,17 @@ ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem,
} }
break; break;
} }
case SUBSYS_SIGNED_BINARY: {
// These rules only need to be added if the
// MITIGATION_FORCE_MS_SIGNED_BINS pre-startup mitigation is set.
if (mitigations_ & MITIGATION_FORCE_MS_SIGNED_BINS) {
if (!SignedPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
NOTREACHED();
return SBOX_ERROR_BAD_PARAMS;
}
}
break;
}
default: { return SBOX_ERROR_UNSUPPORTED; } default: { return SBOX_ERROR_UNSUPPORTED; }
} }
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/win/src/signed_dispatcher.h"
#include <stdint.h>
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/win/scoped_handle.h"
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/interceptors.h"
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/signed_interception.h"
#include "sandbox/win/src/signed_policy.h"
namespace sandbox {
SignedDispatcher::SignedDispatcher(PolicyBase* policy_base)
: policy_base_(policy_base) {
static const IPCCall create_params = {
{IPC_NTCREATESECTION_TAG, {VOIDPTR_TYPE}},
reinterpret_cast<CallbackGeneric>(&SignedDispatcher::CreateSection)};
ipc_calls_.push_back(create_params);
}
bool SignedDispatcher::SetupService(InterceptionManager* manager, int service) {
if (service == IPC_NTCREATESECTION_TAG)
return INTERCEPT_NT(manager, NtCreateSection, CREATE_SECTION_ID, 32);
return false;
}
bool SignedDispatcher::CreateSection(IPCInfo* ipc, HANDLE file_handle) {
// Duplicate input handle from target to broker.
HANDLE local_file_handle = nullptr;
if (!::DuplicateHandle((*ipc->client_info).process, file_handle,
::GetCurrentProcess(), &local_file_handle,
FILE_MAP_EXECUTE, false, 0)) {
return false;
}
base::win::ScopedHandle local_handle(local_file_handle);
base::string16 path;
if (!GetPathFromHandle(local_handle.Get(), &path))
return false;
const wchar_t* module_name = path.c_str();
CountedParameterSet<NameBased> params;
params[NameBased::NAME] = ParamPickerMake(module_name);
EvalResult result =
policy_base_->EvalPolicy(IPC_NTCREATESECTION_TAG, params.GetBase());
// Return operation status on the IPC.
HANDLE section_handle = nullptr;
ipc->return_info.nt_status = SignedPolicy::CreateSectionAction(
result, *ipc->client_info, local_handle, &section_handle);
ipc->return_info.handle = section_handle;
return true;
}
} // namespace sandbox
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_WIN_SRC_SIGNED_DISPATCHER_H_
#define SANDBOX_WIN_SRC_SIGNED_DISPATCHER_H_
#include <stdint.h>
#include "base/macros.h"
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/sandbox_policy_base.h"
namespace sandbox {
// This class handles signed-binary related IPC calls.
class SignedDispatcher : public Dispatcher {
public:
explicit SignedDispatcher(PolicyBase* policy_base);
~SignedDispatcher() override {}
// Dispatcher interface.
bool SetupService(InterceptionManager* manager, int service) override;
private:
// Processes IPC requests coming from calls to CreateSection in the target.
bool CreateSection(IPCInfo* ipc, HANDLE file_handle);
PolicyBase* policy_base_;
DISALLOW_COPY_AND_ASSIGN(SignedDispatcher);
};
} // namespace sandbox
#endif // SANDBOX_WIN_SRC_SIGNED_DISPATCHER_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/win/src/signed_interception.h"
#include <stdint.h>
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/policy_target.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sharedmem_ipc_client.h"
#include "sandbox/win/src/target_services.h"
namespace sandbox {
NTSTATUS WINAPI
TargetNtCreateSection(NtCreateSectionFunction orig_CreateSection,
PHANDLE section_handle,
ACCESS_MASK desired_access,
POBJECT_ATTRIBUTES object_attributes,
PLARGE_INTEGER maximum_size,
ULONG section_page_protection,
ULONG allocation_attributes,
HANDLE file_handle) {
NTSTATUS status = orig_CreateSection(
section_handle, desired_access, object_attributes, maximum_size,
section_page_protection, allocation_attributes, file_handle);
// Only intercept calls that match a particular signature.
if (status != STATUS_INVALID_IMAGE_HASH)
return status;
if (desired_access != (SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ |
SECTION_MAP_EXECUTE))
return status;
if (object_attributes)
return status;
if (maximum_size)
return status;
if (section_page_protection != PAGE_EXECUTE)
return status;
if (allocation_attributes != SEC_IMAGE)
return status;
do {
if (!ValidParameter(section_handle, sizeof(HANDLE), WRITE))
break;
void* memory = GetGlobalIPCMemory();
if (!memory)
break;
std::unique_ptr<wchar_t, NtAllocDeleter> path;
if (!NtGetPathFromHandle(file_handle, &path))
break;
const wchar_t* const_name = path.get();
CountedParameterSet<NameBased> params;
params[NameBased::NAME] = ParamPickerMake(const_name);
if (!QueryBroker(IPC_NTCREATESECTION_TAG, params.GetBase()))
break;
CrossCallReturn answer = {0};
answer.nt_status = status;
SharedMemIPCClient ipc(memory);
ResultCode code =
CrossCall(ipc, IPC_NTCREATESECTION_TAG, file_handle, &answer);
if (code != SBOX_ALL_OK)
break;
status = answer.nt_status;
if (!NT_SUCCESS(answer.nt_status))
break;
__try {
*section_handle = answer.handle;
} __except (EXCEPTION_EXECUTE_HANDLER) {
break;
}
} while (false);
return status;
}
} // namespace sandbox
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_WIN_SRC_SIGNED_INTERCEPTION_H_
#define SANDBOX_WIN_SRC_SIGNED_INTERCEPTION_H_
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
namespace sandbox {
extern "C" {
// Interceptor for NtCreateSection
SANDBOX_INTERCEPT NTSTATUS WINAPI
TargetNtCreateSection(NtCreateSectionFunction orig_CreateSection,
PHANDLE section_handle,
ACCESS_MASK desired_access,
POBJECT_ATTRIBUTES object_attributes,
PLARGE_INTEGER maximum_size,
ULONG section_page_protection,
ULONG allocation_attributes,
HANDLE file_handle);
} // extern "C"
} // namespace sandbox
#endif // SANDBOX_WIN_SRC_SIGNED_INTERCEPTION_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/win/src/signed_policy.h"
#include <stdint.h>
#include <string>
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/policy_engine_opcodes.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/win_utils.h"
namespace sandbox {
bool SignedPolicy::GenerateRules(const wchar_t* name,
TargetPolicy::Semantics semantics,
LowLevelPolicy* policy) {
// Only support one semantic.
if (TargetPolicy::SIGNED_ALLOW_LOAD != semantics) {
return false;
}
base::FilePath file_path(name);
base::string16 nt_path_name;
if (!GetNtPathFromWin32Path(file_path.DirName().value().c_str(),
&nt_path_name))
return false;
base::FilePath nt_path(nt_path_name);
base::string16 nt_filename = nt_path.Append(file_path.BaseName()).value();
// Create a rule to ASK_BROKER if name matches.
PolicyRule signed_policy(ASK_BROKER);
if (!signed_policy.AddStringMatch(IF, NameBased::NAME, nt_filename.c_str(),
CASE_INSENSITIVE)) {
return false;
}
if (!policy->AddRule(IPC_NTCREATESECTION_TAG, &signed_policy)) {
return false;
}
return true;
}
NTSTATUS SignedPolicy::CreateSectionAction(
EvalResult eval_result,
const ClientInfo& client_info,
const base::win::ScopedHandle& local_file_handle,
HANDLE* target_section_handle) {
NtCreateSectionFunction NtCreateSection = nullptr;
ResolveNTFunctionPtr("NtCreateSection", &NtCreateSection);
// The only action supported is ASK_BROKER which means create the requested
// section as specified.
if (ASK_BROKER != eval_result)
return false;
HANDLE local_section_handle = nullptr;
NTSTATUS status = NtCreateSection(&local_section_handle,
SECTION_QUERY | SECTION_MAP_WRITE |
SECTION_MAP_READ | SECTION_MAP_EXECUTE,
nullptr, 0, PAGE_EXECUTE, SEC_IMAGE,
local_file_handle.Get());
if (!local_section_handle)
return status;
// Duplicate section handle back to the target.
if (!::DuplicateHandle(::GetCurrentProcess(), local_section_handle,
client_info.process, target_section_handle, 0, false,
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
return STATUS_ACCESS_DENIED;
}
return status;
}
} // namespace sandbox
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_WIN_SRC_SIGNED_POLICY_H_
#define SANDBOX_WIN_SRC_SIGNED_POLICY_H_
#include <stdint.h>
#include "base/win/scoped_handle.h"
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/policy_engine_opcodes.h"
#include "sandbox/win/src/policy_low_level.h"
#include "sandbox/win/src/sandbox_policy.h"
namespace sandbox {
// This class centralizes most of the knowledge related to signed policy
class SignedPolicy {
public:
// Creates the required low-level policy rules to evaluate a high-level
// policy rule.
static bool GenerateRules(const wchar_t* name,
TargetPolicy::Semantics semantics,
LowLevelPolicy* policy);
// Performs the desired policy action on a request.
// client_info is the target process that is making the request and
// eval_result is the desired policy action to accomplish.
static NTSTATUS CreateSectionAction(
EvalResult eval_result,
const ClientInfo& client_info,
const base::win::ScopedHandle& local_file_handle,
HANDLE* section_handle);
};
} // namespace sandbox
#endif // SANDBOX_WIN_SRC_SIGNED_POLICY_H_
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "sandbox/win/src/process_thread_dispatcher.h" #include "sandbox/win/src/process_thread_dispatcher.h"
#include "sandbox/win/src/registry_dispatcher.h" #include "sandbox/win/src/registry_dispatcher.h"
#include "sandbox/win/src/sandbox_policy_base.h" #include "sandbox/win/src/sandbox_policy_base.h"
#include "sandbox/win/src/signed_dispatcher.h"
#include "sandbox/win/src/sync_dispatcher.h" #include "sandbox/win/src/sync_dispatcher.h"
namespace sandbox { namespace sandbox {
...@@ -76,6 +77,10 @@ TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) { ...@@ -76,6 +77,10 @@ TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) {
dispatcher; dispatcher;
ipc_targets_[IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG] = dispatcher; ipc_targets_[IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG] = dispatcher;
process_mitigations_win32k_dispatcher_.reset(dispatcher); process_mitigations_win32k_dispatcher_.reset(dispatcher);
dispatcher = new SignedDispatcher(policy_);
ipc_targets_[IPC_NTCREATESECTION_TAG] = dispatcher;
signed_dispatcher_.reset(dispatcher);
} }
TopLevelDispatcher::~TopLevelDispatcher() {} TopLevelDispatcher::~TopLevelDispatcher() {}
......
...@@ -42,6 +42,7 @@ class TopLevelDispatcher : public Dispatcher { ...@@ -42,6 +42,7 @@ class TopLevelDispatcher : public Dispatcher {
std::unique_ptr<Dispatcher> registry_dispatcher_; std::unique_ptr<Dispatcher> registry_dispatcher_;
std::unique_ptr<Dispatcher> handle_dispatcher_; std::unique_ptr<Dispatcher> handle_dispatcher_;
std::unique_ptr<Dispatcher> process_mitigations_win32k_dispatcher_; std::unique_ptr<Dispatcher> process_mitigations_win32k_dispatcher_;
std::unique_ptr<Dispatcher> signed_dispatcher_;
Dispatcher* ipc_targets_[IPC_LAST_TAG]; Dispatcher* ipc_targets_[IPC_LAST_TAG];
DISALLOW_COPY_AND_ASSIGN(TopLevelDispatcher); DISALLOW_COPY_AND_ASSIGN(TopLevelDispatcher);
......
...@@ -41,5 +41,6 @@ src:*process_thread_interception.cc ...@@ -41,5 +41,6 @@ src:*process_thread_interception.cc
src:*registry_interception.cc src:*registry_interception.cc
src:*resolver_32.cc src:*resolver_32.cc
src:*sandbox_nt_util.cc src:*sandbox_nt_util.cc
src:*signed_interception.cc
src:*sync_interception.cc src:*sync_interception.cc
################################################################################ ################################################################################
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment