summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authorjschuh@chromium.org <jschuh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-13 15:08:36 +0000
committerjschuh@chromium.org <jschuh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-13 15:08:36 +0000
commita38d2e10b905b3be8316f235403ac2c49cead029 (patch)
tree3744c13489eba26db87e8bc5925f0ec724a751cb /sandbox
parenta155abbffdce8ecfef657cca7c0b58d092b7e4b8 (diff)
downloadchromium_src-a38d2e10b905b3be8316f235403ac2c49cead029.zip
chromium_src-a38d2e10b905b3be8316f235403ac2c49cead029.tar.gz
chromium_src-a38d2e10b905b3be8316f235403ac2c49cead029.tar.bz2
Add sandbox support for Windows process mitigations
BUG=147752 Review URL: https://codereview.chromium.org/10690058 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@156550 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/win/sandbox_win.gypi6
-rw-r--r--sandbox/win/src/broker_services.cc37
-rw-r--r--sandbox/win/src/dep.cc89
-rw-r--r--sandbox/win/src/dep.h25
-rw-r--r--sandbox/win/src/dep_test.cc158
-rw-r--r--sandbox/win/src/nt_internals.h16
-rw-r--r--sandbox/win/src/process_mitigations.cc312
-rw-r--r--sandbox/win/src/process_mitigations.h44
-rw-r--r--sandbox/win/src/process_mitigations_test.cc203
-rw-r--r--sandbox/win/src/sandbox_policy.h16
-rw-r--r--sandbox/win/src/sandbox_policy_base.cc46
-rw-r--r--sandbox/win/src/sandbox_policy_base.h7
-rw-r--r--sandbox/win/src/sandbox_types.h5
-rw-r--r--sandbox/win/src/security_level.h58
-rw-r--r--sandbox/win/src/target_process.cc23
-rw-r--r--sandbox/win/src/target_services.cc6
-rw-r--r--sandbox/win/tests/common/controller.h4
17 files changed, 746 insertions, 309 deletions
diff --git a/sandbox/win/sandbox_win.gypi b/sandbox/win/sandbox_win.gypi
index 7160bf7..0b3f590 100644
--- a/sandbox/win/sandbox_win.gypi
+++ b/sandbox/win/sandbox_win.gypi
@@ -22,8 +22,6 @@
'src/crosscall_params.h',
'src/crosscall_server.cc',
'src/crosscall_server.h',
- 'src/dep.cc',
- 'src/dep.h',
'src/eat_resolver.cc',
'src/eat_resolver.h',
'src/filesystem_dispatcher.cc',
@@ -73,6 +71,8 @@
'src/policy_params.h',
'src/policy_target.cc',
'src/policy_target.h',
+ 'src/process_mitigations.cc',
+ 'src/process_mitigations.h',
'src/process_thread_dispatcher.cc',
'src/process_thread_dispatcher.h',
'src/process_thread_interception.cc',
@@ -232,7 +232,6 @@
],
'sources': [
'src/app_container_test.cc',
- 'src/dep_test.cc',
'src/file_policy_test.cc',
'src/handle_policy_test.cc',
'tests/integration_tests/integration_tests_test.cc',
@@ -241,6 +240,7 @@
'src/ipc_ping_test.cc',
'src/named_pipe_policy_test.cc',
'src/policy_target_test.cc',
+ 'src/process_mitigations_test.cc',
'src/process_policy_test.cc',
'src/registry_policy_test.cc',
'src/sync_policy_test.cc',
diff --git a/sandbox/win/src/broker_services.cc b/sandbox/win/src/broker_services.cc
index 497f2f8..0425845 100644
--- a/sandbox/win/src/broker_services.cc
+++ b/sandbox/win/src/broker_services.cc
@@ -12,6 +12,7 @@
#include "base/win/startup_information.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/app_container.h"
+#include "sandbox/win/src/process_mitigations.h"
#include "sandbox/win/src/sandbox_policy_base.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/target_process.h"
@@ -320,12 +321,36 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
const_cast<wchar_t*>(desktop.c_str());
}
- const AppContainerAttributes* app_container = policy_base->GetAppContainer();
- if (app_container) {
- startup_info.InitializeProcThreadAttributeList(1);
- result = app_container->ShareForStartup(&startup_info);
- if (SBOX_ALL_OK != result)
- return result;
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ int attribute_count = 0;
+ const AppContainerAttributes* app_container =
+ policy_base->GetAppContainer();
+ if (app_container)
+ ++attribute_count;
+
+ DWORD64 mitigations;
+ size_t mitigations_size;
+ ConvertProcessMitigationsToPolicy(policy->GetProcessMitigations(),
+ &mitigations, &mitigations_size);
+ if (mitigations)
+ ++attribute_count;
+
+ if (!startup_info.InitializeProcThreadAttributeList(attribute_count))
+ return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
+
+ if (app_container) {
+ result = app_container->ShareForStartup(&startup_info);
+ if (SBOX_ALL_OK != result)
+ return result;
+ }
+
+ if (mitigations) {
+ if (!startup_info.UpdateProcThreadAttribute(
+ PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &mitigations,
+ mitigations_size)) {
+ return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
+ }
+ }
}
// Construct the thread pool here in case it is expensive.
diff --git a/sandbox/win/src/dep.cc b/sandbox/win/src/dep.cc
deleted file mode 100644
index 0c42050..0000000
--- a/sandbox/win/src/dep.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2006-2008 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/dep.h"
-
-#include <windows.h>
-
-#include "base/logging.h"
-
-namespace sandbox {
-
-namespace {
-
-// These values are in the Windows 2008 SDK but not in the previous ones. Define
-// the values here until we're sure everyone updated their SDK.
-#ifndef PROCESS_DEP_ENABLE
-#define PROCESS_DEP_ENABLE 0x00000001
-#endif
-#ifndef PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
-#define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
-#endif
-
-// SetProcessDEPPolicy is declared in the Windows 2008 SDK.
-typedef BOOL (WINAPI *FnSetProcessDEPPolicy)(DWORD dwFlags);
-
-enum PROCESS_INFORMATION_CLASS {
- ProcessExecuteFlags = 0x22,
-};
-
-// Flags named as per their usage.
-const int MEM_EXECUTE_OPTION_ENABLE = 1;
-const int MEM_EXECUTE_OPTION_DISABLE = 2;
-const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4;
-const int MEM_EXECUTE_OPTION_PERMANENT = 8;
-
-// Not exactly the right signature but that will suffice.
-typedef HRESULT (WINAPI *FnNtSetInformationProcess)(
- HANDLE ProcessHandle,
- PROCESS_INFORMATION_CLASS ProcessInformationClass,
- PVOID ProcessInformation,
- ULONG ProcessInformationLength);
-
-} // namespace
-
-bool SetCurrentProcessDEP(DepEnforcement enforcement) {
-#ifdef _WIN64
- // DEP is always on in x64.
- return enforcement != DEP_DISABLED;
-#endif
- // Only available on Windows XP SP2 and Windows Server 2003 SP1.
- // For reference: http://www.uninformed.org/?v=2&a=4
- FnNtSetInformationProcess NtSetInformationProc =
- reinterpret_cast<FnNtSetInformationProcess>(
- GetProcAddress(GetModuleHandle(L"ntdll.dll"),
- "NtSetInformationProcess"));
-
- if (!NtSetInformationProc)
- return false;
-
- // Flags being used as per SetProcessDEPPolicy on Vista SP1.
- ULONG dep_flags;
- switch (enforcement) {
- case DEP_DISABLED:
- // 2
- dep_flags = MEM_EXECUTE_OPTION_DISABLE;
- break;
- case DEP_ENABLED:
- // 9
- dep_flags = MEM_EXECUTE_OPTION_PERMANENT | MEM_EXECUTE_OPTION_ENABLE;
- break;
- case DEP_ENABLED_ATL7_COMPAT:
- // 0xD
- dep_flags = MEM_EXECUTE_OPTION_PERMANENT | MEM_EXECUTE_OPTION_ENABLE |
- MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION;
- break;
- default:
- NOTREACHED();
- return false;
- }
-
- HRESULT status = NtSetInformationProc(GetCurrentProcess(),
- ProcessExecuteFlags,
- &dep_flags,
- sizeof(dep_flags));
- return SUCCEEDED(status);
-}
-
-} // namespace sandbox
diff --git a/sandbox/win/src/dep.h b/sandbox/win/src/dep.h
deleted file mode 100644
index 9016285..0000000
--- a/sandbox/win/src/dep.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2006-2008 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_SRC_DEP_H__
-#define SANDBOX_SRC_DEP_H__
-
-namespace sandbox {
-
-enum DepEnforcement {
- // DEP is completely disabled.
- DEP_DISABLED,
- // DEP is permanently enforced.
- DEP_ENABLED,
- // DEP with support for ATL7 thunking is permanently enforced.
- DEP_ENABLED_ATL7_COMPAT,
-};
-
-// Change the Data Execution Prevention (DEP) status for the current process.
-// Once enabled, it cannot be disabled.
-bool SetCurrentProcessDEP(DepEnforcement enforcement);
-
-} // namespace sandbox
-
-#endif // SANDBOX_SRC_DEP_H__
diff --git a/sandbox/win/src/dep_test.cc b/sandbox/win/src/dep_test.cc
deleted file mode 100644
index 2817caa..0000000
--- a/sandbox/win/src/dep_test.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (c) 2011 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/dep.h"
-
-#include "sandbox/win/src/sandbox_utils.h"
-#include "sandbox/win/tests/common/controller.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace sandbox {
-
-namespace {
-
-BYTE kReturnCode[] = {
- // ret
- 0xC3,
-};
-
-typedef void (*NullFunction)();
-
-// This doesn't fail on Vista Service Pack 0 but it does on XP SP2 and Vista
-// SP1. I guess this is a bug in Vista SP0 w.r.t .data PE section. Needs
-// investigation to be sure it is a bug and not an error on my part.
-bool GenerateDepException() {
- bool result = false;
- __try {
- void* code = kReturnCode;
- // Call this code.
- reinterpret_cast<NullFunction>(code)();
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- result = true;
- }
- return result;
-}
-
-bool GenerateDepAtl7Exception() {
- // TODO(maruel): bug 1207762 Somehow test ATL7
- return GenerateDepException();
-}
-
-SBOX_TESTS_COMMAND int CheckDepLevel(int argc, wchar_t **argv) {
- if (1 != argc)
- return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-
- int flag = _wtoi(argv[0]);
- switch (flag) {
- case 1:
- // DEP is completely disabled.
- if (!SetCurrentProcessDEP(DEP_DISABLED)) {
- if (!IsXPSP2OrLater())
- // That's fine.
- return SBOX_TEST_SUCCEEDED;
- return SBOX_TEST_DENIED;
- }
- if (GenerateDepException())
- return SBOX_TEST_FAILED;
- if (GenerateDepAtl7Exception())
- return SBOX_TEST_FAILED;
- return SBOX_TEST_SUCCEEDED;
- case 2:
- // DEP is enabled with ATL7 thunk support.
- if (!SetCurrentProcessDEP(DEP_ENABLED_ATL7_COMPAT)) {
- if (!IsXPSP2OrLater())
- // That's fine.
- return SBOX_TEST_SUCCEEDED;
- return SBOX_TEST_DENIED;
- }
- if (!GenerateDepException())
- return SBOX_TEST_FAILED;
- if (GenerateDepAtl7Exception())
- return SBOX_TEST_FAILED;
- return SBOX_TEST_SUCCEEDED;
- case 3:
- // DEP is enabled.
- if (!SetCurrentProcessDEP(DEP_ENABLED)) {
- if (!IsXPSP2OrLater())
- // That's fine.
- return SBOX_TEST_SUCCEEDED;
- return SBOX_TEST_DENIED;
- }
- if (!GenerateDepException())
- return SBOX_TEST_FAILED;
- if (!GenerateDepAtl7Exception())
- return SBOX_TEST_FAILED;
- return SBOX_TEST_SUCCEEDED;
- case 4:
- // DEP can't be disabled.
- if (!SetCurrentProcessDEP(DEP_ENABLED)) {
- if (!IsXPSP2OrLater())
- // That's fine.
- return SBOX_TEST_SUCCEEDED;
- }
- if (SetCurrentProcessDEP(DEP_DISABLED)) {
- return SBOX_TEST_DENIED;
- }
- // Verify that it is still enabled.
- if (!GenerateDepException())
- return SBOX_TEST_FAILED;
- if (!GenerateDepAtl7Exception())
- return SBOX_TEST_FAILED;
- return SBOX_TEST_SUCCEEDED;
- case 5:
- // DEP can't be disabled.
- if (!SetCurrentProcessDEP(DEP_ENABLED_ATL7_COMPAT)) {
- if (!IsXPSP2OrLater())
- // That's fine.
- return SBOX_TEST_SUCCEEDED;
- }
- if (SetCurrentProcessDEP(DEP_DISABLED)) {
- return SBOX_TEST_DENIED;
- }
- // Verify that it is still enabled.
- if (!GenerateDepException())
- return SBOX_TEST_FAILED;
- if (!GenerateDepAtl7Exception())
- return SBOX_TEST_FAILED;
- return SBOX_TEST_SUCCEEDED;
- case 6:
- // DEP can't be disabled.
- if (!SetCurrentProcessDEP(DEP_ENABLED)) {
- if (!IsXPSP2OrLater())
- // That's fine.
- return SBOX_TEST_SUCCEEDED;
- }
- if (SetCurrentProcessDEP(DEP_ENABLED_ATL7_COMPAT)) {
- return SBOX_TEST_DENIED;
- }
- // Verify that it is still enabled.
- if (!GenerateDepException())
- return SBOX_TEST_FAILED;
- if (!GenerateDepAtl7Exception())
- return SBOX_TEST_FAILED;
- return SBOX_TEST_SUCCEEDED;
- default:
- return SBOX_TEST_INVALID_PARAMETER;
- }
- return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
-}
-
-} // namespace
-
-// This test is disabled. See bug 1275842
-TEST(DepTest, DISABLED_TestDepDisable) {
- TestRunner runner(JOB_UNPROTECTED, USER_INTERACTIVE, USER_INTERACTIVE);
-
- runner.SetTimeout(INFINITE);
-
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDepLevel 1"));
- // TODO(maruel): bug 1207762 Somehow test ATL7
- // EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDepLevel 2"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDepLevel 3"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDepLevel 4"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDepLevel 5"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDepLevel 6"));
-}
-
-} // namespace sandbox
diff --git a/sandbox/win/src/nt_internals.h b/sandbox/win/src/nt_internals.h
index fe4fcd6..c9aaf92 100644
--- a/sandbox/win/src/nt_internals.h
+++ b/sandbox/win/src/nt_internals.h
@@ -4,8 +4,8 @@
// This file holds definitions related to the ntdll API.
-#ifndef SANDBOX_SRC_NT_INTERNALS_H__
-#define SANDBOX_SRC_NT_INTERNALS_H__
+#ifndef SANDBOX_WIN_SRC_NT_INTERNALS_H__
+#define SANDBOX_WIN_SRC_NT_INTERNALS_H__
#include <windows.h>
@@ -292,7 +292,8 @@ typedef NTSTATUS (WINAPI *NtSetInformationThreadFunction) (
// Partial definition only:
typedef enum _PROCESSINFOCLASS {
- ProcessBasicInformation = 0
+ ProcessBasicInformation = 0,
+ ProcessExecuteFlags = 0x22
} PROCESSINFOCLASS;
typedef PVOID PPEB;
@@ -314,6 +315,12 @@ typedef NTSTATUS (WINAPI *NtQueryInformationProcessFunction)(
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL);
+typedef NTSTATUS (WINAPI *NtSetInformationProcessFunction)(
+ HANDLE ProcessHandle,
+ IN PROCESSINFOCLASS ProcessInformationClass,
+ IN PVOID ProcessInformation,
+ IN ULONG ProcessInformationLength);
+
typedef NTSTATUS (WINAPI *NtOpenThreadTokenFunction) (
IN HANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
@@ -608,4 +615,5 @@ typedef VOID (WINAPI *RtlInitUnicodeStringFunction) (
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString);
-#endif // SANDBOX_SRC_NT_INTERNALS_H__
+#endif // SANDBOX_WIN_SRC_NT_INTERNALS_H__
+
diff --git a/sandbox/win/src/process_mitigations.cc b/sandbox/win/src/process_mitigations.cc
new file mode 100644
index 0000000..17b2227
--- /dev/null
+++ b/sandbox/win/src/process_mitigations.cc
@@ -0,0 +1,312 @@
+// Copyright (c) 2012 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/process_mitigations.h"
+
+#include "base/win/windows_version.h"
+#include "sandbox/win/src/nt_internals.h"
+#include "sandbox/win/src/sandbox_utils.h"
+#include "sandbox/win/src/win_utils.h"
+
+namespace {
+
+// Functions for enabling policies.
+typedef BOOL (WINAPI *SetProcessDEPPolicyFunction)(DWORD dwFlags);
+
+typedef BOOL (WINAPI *SetProcessMitigationPolicyFunction)(
+ PROCESS_MITIGATION_POLICY mitigation_policy,
+ PVOID buffer,
+ SIZE_T length);
+
+typedef BOOL (WINAPI *SetDefaultDllDirectoriesFunction)(
+ DWORD DirectoryFlags);
+
+} // namespace
+
+namespace sandbox {
+
+bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags) {
+ if (!CanSetProcessMitigationsPostStartup(flags))
+ return false;
+
+ // We can't apply anything before Win XP, so just return cleanly.
+ if (!IsXPSP2OrLater())
+ return true;
+
+ HMODULE module = ::GetModuleHandleA("kernel32.dll");
+
+ if (flags & MITIGATION_DLL_SEARCH_ORDER) {
+ SetDefaultDllDirectoriesFunction set_default_dll_directories =
+ reinterpret_cast<SetDefaultDllDirectoriesFunction>(
+ ::GetProcAddress(module, "SetDefaultDllDirectories"));
+
+ // Check for SetDefaultDllDirectories since it requires KB2533623.
+ if (set_default_dll_directories) {
+ if (!set_default_dll_directories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS))
+ return false;
+ }
+ }
+
+ // Set the heap to terminate on corruption
+ if (flags & MITIGATION_HEAP_TERMINATE) {
+ if (!::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption,
+ NULL, 0))
+ return false;
+ }
+
+#if !defined(_WIN64) // DEP is always enabled on 64-bit.
+ if (flags & MITIGATION_DEP) {
+ DWORD dep_flags = PROCESS_DEP_ENABLE;
+
+ if (flags & MITIGATION_DEP_NO_ATL_THUNK)
+ dep_flags |= PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION;
+
+ SetProcessDEPPolicyFunction set_process_dep_policy =
+ reinterpret_cast<SetProcessDEPPolicyFunction>(
+ ::GetProcAddress(module, "SetProcessDEPPolicy"));
+ if (set_process_dep_policy) {
+ if (!set_process_dep_policy(dep_flags) &&
+ ERROR_ACCESS_DENIED != ::GetLastError()) {
+ return false;
+ }
+ } else {
+ // We're on XP sp2, so use the less standard approach.
+ // For reference: http://www.uninformed.org/?v=2&a=4
+ const int MEM_EXECUTE_OPTION_ENABLE = 1;
+ const int MEM_EXECUTE_OPTION_DISABLE = 2;
+ const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4;
+ const int MEM_EXECUTE_OPTION_PERMANENT = 8;
+
+ NtSetInformationProcessFunction set_information_process = NULL;
+ ResolveNTFunctionPtr("NtSetInformationProcess",
+ &set_information_process);
+ if (!set_information_process)
+ return false;
+ ULONG dep = MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_PERMANENT;
+ if (!(dep_flags & PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION))
+ dep |= MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION;
+ if (!SUCCEEDED(set_information_process(GetCurrentProcess(),
+ ProcessExecuteFlags,
+ &dep, sizeof(dep))) &&
+ ERROR_ACCESS_DENIED != ::GetLastError()) {
+ return false;
+ }
+ }
+ }
+#endif
+
+ // This is all we can do in Win7 and below.
+ base::win::Version version = base::win::GetVersion();
+ if (version < base::win::VERSION_WIN8)
+ return true;
+
+ SetProcessMitigationPolicyFunction set_process_mitigation_policy =
+ reinterpret_cast<SetProcessMitigationPolicyFunction>(
+ ::GetProcAddress(module, "SetProcessMitigationPolicy"));
+ if (!set_process_mitigation_policy)
+ return false;
+
+ // Enable ASLR policies.
+ if (flags & MITIGATION_RELOCATE_IMAGE) {
+ PROCESS_MITIGATION_ASLR_POLICY policy = { 0 };
+ policy.EnableForceRelocateImages = true;
+ policy.DisallowStrippedImages = (flags &
+ MITIGATION_RELOCATE_IMAGE_REQUIRED) ==
+ MITIGATION_RELOCATE_IMAGE_REQUIRED;
+
+ if (!set_process_mitigation_policy(ProcessASLRPolicy, &policy,
+ sizeof(policy)) &&
+ ERROR_ACCESS_DENIED != ::GetLastError()) {
+ return false;
+ }
+ }
+
+ // Enable strict handle policies.
+ if (flags & MITIGATION_STRICT_HANDLE_CHECKS) {
+ PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy = { 0 };
+ policy.HandleExceptionsPermanentlyEnabled =
+ policy.RaiseExceptionOnInvalidHandleReference = true;
+
+ if (!set_process_mitigation_policy(ProcessStrictHandleCheckPolicy, &policy,
+ sizeof(policy)) &&
+ ERROR_ACCESS_DENIED != ::GetLastError()) {
+ return false;
+ }
+ }
+
+ // Enable system call policies.
+ if (flags & MITIGATION_WIN32K_DISABLE) {
+ PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = { 0 };
+ policy.DisallowWin32kSystemCalls = true;
+
+ if (!set_process_mitigation_policy(ProcessSystemCallDisablePolicy, &policy,
+ sizeof(policy)) &&
+ ERROR_ACCESS_DENIED != ::GetLastError()) {
+ return false;
+ }
+ }
+
+ // Enable system call policies.
+ if (flags & MITIGATION_EXTENSION_DLL_DISABLE) {
+ PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = { 0 };
+ policy.DisableExtensionPoints = true;
+
+ if (!set_process_mitigation_policy(ProcessExtensionPointDisablePolicy,
+ &policy, sizeof(policy)) &&
+ ERROR_ACCESS_DENIED != ::GetLastError()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void ConvertProcessMitigationsToPolicy(MitigationFlags flags,
+ DWORD64* policy_flags, size_t* size) {
+ base::win::Version version = base::win::GetVersion();
+
+ *policy_flags = 0;
+#if defined(_WIN64)
+ *size = sizeof(*policy_flags);
+#elif defined(_M_IX86)
+ // A 64-bit flags attribute is illegal on 32-bit Win 7 and below.
+ if (version < base::win::VERSION_WIN8)
+ *size = sizeof(DWORD);
+ else
+ *size = sizeof(*policy_flags);
+#else
+#error This platform is not supported.
+#endif
+
+ // Nothing for Win XP.
+ if (version < base::win::VERSION_VISTA)
+ return;
+
+ if (flags & MITIGATION_DEP) {
+ *policy_flags |= PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE;
+ if (!(flags & MITIGATION_DEP_NO_ATL_THUNK))
+ *policy_flags |= PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE;
+ }
+
+ if (flags & MITIGATION_SEHOP)
+ *policy_flags |= PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE;
+
+ // Win 7 and Vista
+ if (version < base::win::VERSION_WIN8)
+ return;
+
+ if (flags & MITIGATION_RELOCATE_IMAGE) {
+ *policy_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON;
+ if (flags & MITIGATION_RELOCATE_IMAGE_REQUIRED) {
+ *policy_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON_REQ_RELOCS;
+ }
+ }
+
+ if (flags & MITIGATION_HEAP_TERMINATE) {
+ *policy_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_HEAP_TERMINATE_ALWAYS_ON;
+ }
+
+ if (flags & MITIGATION_BOTTOM_UP_ASLR) {
+ *policy_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_ON;
+ }
+
+ if (flags & MITIGATION_HIGH_ENTROPY_ASLR) {
+ *policy_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_HIGH_ENTROPY_ASLR_ALWAYS_ON;
+ }
+
+ if (flags & MITIGATION_STRICT_HANDLE_CHECKS) {
+ *policy_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON;
+ }
+
+ if (flags & MITIGATION_WIN32K_DISABLE) {
+ *policy_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON;
+ }
+
+ if (flags & MITIGATION_EXTENSION_DLL_DISABLE) {
+ *policy_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON;
+ }
+}
+
+MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags) {
+ // Anything prior to XP SP2.
+ if (!IsXPSP2OrLater())
+ return 0;
+
+ base::win::Version version = base::win::GetVersion();
+
+ // Windows XP SP2+.
+ if (version < base::win::VERSION_VISTA) {
+ return flags & (MITIGATION_DEP |
+ MITIGATION_DEP_NO_ATL_THUNK);
+
+ // Windows 7 and Vista.
+ } else if (version < base::win::VERSION_WIN8) {
+ return flags & (MITIGATION_BOTTOM_UP_ASLR |
+ MITIGATION_DLL_SEARCH_ORDER |
+ MITIGATION_HEAP_TERMINATE);
+ }
+
+ // Windows 8 and above.
+ return flags & (MITIGATION_BOTTOM_UP_ASLR |
+ MITIGATION_DLL_SEARCH_ORDER);
+}
+
+bool ApplyProcessMitigationsToSuspendedProcess(HANDLE process,
+ MitigationFlags flags) {
+// This is a hack to fake a weak bottom-up ASLR on 32-bit Windows.
+#if !defined(_WIN64)
+ if (flags & MITIGATION_BOTTOM_UP_ASLR) {
+ unsigned int limit;
+ rand_s(&limit);
+ char* ptr = 0;
+ const size_t kMask64k = 0xFFFF;
+ // Random range (512k-16.5mb) in 64k steps.
+ const char* end = ptr + ((((limit % 16384) + 512) * 1024) & ~kMask64k);
+ while (ptr < end) {
+ MEMORY_BASIC_INFORMATION memory_info;
+ if (!::VirtualQueryEx(process, ptr, &memory_info, sizeof(memory_info)))
+ break;
+ size_t size = std::min((memory_info.RegionSize + kMask64k) & ~kMask64k,
+ static_cast<SIZE_T>(end - ptr));
+ if (ptr && memory_info.State == MEM_FREE)
+ ::VirtualAllocEx(process, ptr, size, MEM_RESERVE, PAGE_NOACCESS);
+ ptr += size;
+ }
+ }
+#endif
+
+ return true;
+}
+
+bool CanSetProcessMitigationsPostStartup(MitigationFlags flags) {
+ // All of these mitigations can be enabled after startup.
+ return !(flags & ~(MITIGATION_HEAP_TERMINATE |
+ MITIGATION_DEP |
+ MITIGATION_DEP_NO_ATL_THUNK |
+ MITIGATION_RELOCATE_IMAGE |
+ MITIGATION_RELOCATE_IMAGE_REQUIRED |
+ MITIGATION_BOTTOM_UP_ASLR |
+ MITIGATION_STRICT_HANDLE_CHECKS |
+ MITIGATION_WIN32K_DISABLE |
+ MITIGATION_EXTENSION_DLL_DISABLE |
+ MITIGATION_DLL_SEARCH_ORDER));
+}
+
+bool CanSetProcessMitigationsPreStartup(MitigationFlags flags) {
+ // These mitigations cannot be enabled prior to startup.
+ return !(flags & (MITIGATION_STRICT_HANDLE_CHECKS |
+ MITIGATION_WIN32K_DISABLE |
+ MITIGATION_DLL_SEARCH_ORDER));
+}
+
+} // namespace sandbox
+
diff --git a/sandbox/win/src/process_mitigations.h b/sandbox/win/src/process_mitigations.h
new file mode 100644
index 0000000..9039ad6
--- /dev/null
+++ b/sandbox/win/src/process_mitigations.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2012 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_SRC_WIN_PROCESS_MITIGATIONS_H_
+#define SANDBOX_SRC_WIN_PROCESS_MITIGATIONS_H_
+
+#include <windows.h>
+
+#include "base/basictypes.h"
+#include "sandbox/win/src/security_level.h"
+
+namespace sandbox {
+
+// Sets the mitigation policy for the current process, ignoring any settings
+// that are invalid for the current version of Windows.
+bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags);
+
+// Returns the flags that must be enforced after startup for the current OS
+// version.
+MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags);
+
+// Converts sandbox flags to the PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES
+// policy flags used by UpdateProcThreadAttribute(). The size field varies
+// between a 32-bit and a 64-bit type based on the exact build and version of
+// Windows, so the returned size must be passed to UpdateProcThreadAttribute().
+void ConvertProcessMitigationsToPolicy(MitigationFlags flags,
+ DWORD64* policy_flags, size_t* size);
+
+// Adds mitigations that need to be performed on the suspended target process
+// before execution begins.
+bool ApplyProcessMitigationsToSuspendedProcess(HANDLE process,
+ MitigationFlags flags);
+
+// Returns true if all the supplied flags can be set after a process starts.
+bool CanSetProcessMitigationsPostStartup(MitigationFlags flags);
+
+// Returns true if all the supplied flags can be set before a process starts.
+bool CanSetProcessMitigationsPreStartup(MitigationFlags flags);
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_WIN_PROCESS_MITIGATIONS_H_
+
diff --git a/sandbox/win/src/process_mitigations_test.cc b/sandbox/win/src/process_mitigations_test.cc
new file mode 100644
index 0000000..2456391
--- /dev/null
+++ b/sandbox/win/src/process_mitigations_test.cc
@@ -0,0 +1,203 @@
+// Copyright (c) 2011 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 "base/stringprintf.h"
+#include "base/win/scoped_handle.h"
+
+#include "base/win/windows_version.h"
+#include "sandbox/win/src/nt_internals.h"
+#include "sandbox/win/src/process_mitigations.h"
+#include "sandbox/win/src/sandbox.h"
+#include "sandbox/win/src/sandbox_factory.h"
+#include "sandbox/win/src/sandbox_utils.h"
+#include "sandbox/win/src/target_services.h"
+#include "sandbox/win/src/win_utils.h"
+#include "sandbox/win/tests/common/controller.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+typedef BOOL (WINAPI *GetProcessDEPPolicyFunction)(
+ HANDLE process,
+ LPDWORD flags,
+ PBOOL permanent);
+
+typedef BOOL (WINAPI *GetProcessMitigationPolicyFunction)(
+ HANDLE process,
+ PROCESS_MITIGATION_POLICY mitigation_policy,
+ PVOID buffer,
+ SIZE_T length);
+
+GetProcessMitigationPolicyFunction get_process_mitigation_policy;
+
+bool CheckWin8DepPolicy() {
+ PROCESS_MITIGATION_DEP_POLICY policy;
+ if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy,
+ &policy, sizeof(policy))) {
+ return false;
+ }
+ return policy.Enable && policy.Permanent;
+}
+
+bool CheckWin8AslrPolicy() {
+ PROCESS_MITIGATION_ASLR_POLICY policy;
+ if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy,
+ &policy, sizeof(policy))) {
+ return false;
+ }
+ return policy.EnableForceRelocateImages && policy.DisallowStrippedImages;
+}
+
+bool CheckWin8StrictHandlePolicy() {
+ PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy;
+ if (!get_process_mitigation_policy(::GetCurrentProcess(),
+ ProcessStrictHandleCheckPolicy,
+ &policy, sizeof(policy))) {
+ return false;
+ }
+ return policy.RaiseExceptionOnInvalidHandleReference &&
+ policy.HandleExceptionsPermanentlyEnabled;
+}
+
+bool CheckWin8Win32CallPolicy() {
+ PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy;
+ if (!get_process_mitigation_policy(::GetCurrentProcess(),
+ ProcessSystemCallDisablePolicy,
+ &policy, sizeof(policy))) {
+ return false;
+ }
+ return policy.DisallowWin32kSystemCalls;
+}
+
+bool CheckWin8DllExtensionPolicy() {
+ PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy;
+ if (!get_process_mitigation_policy(::GetCurrentProcess(),
+ ProcessExtensionPointDisablePolicy,
+ &policy, sizeof(policy))) {
+ return false;
+ }
+ return policy.DisableExtensionPoints;
+}
+
+} // namespace
+
+namespace sandbox {
+
+SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) {
+ get_process_mitigation_policy =
+ reinterpret_cast<GetProcessMitigationPolicyFunction>(
+ ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"),
+ "GetProcessMitigationPolicy"));
+
+ if (!get_process_mitigation_policy)
+ return SBOX_TEST_NOT_FOUND;
+
+ if (!CheckWin8DepPolicy())
+ return SBOX_TEST_FIRST_ERROR;
+
+ if (!CheckWin8AslrPolicy())
+ return SBOX_TEST_SECOND_ERROR;
+
+ if (!CheckWin8StrictHandlePolicy())
+ return SBOX_TEST_THIRD_ERROR;
+
+ if (!CheckWin8Win32CallPolicy())
+ return SBOX_TEST_FOURTH_ERROR;
+
+ if (!CheckWin8DllExtensionPolicy())
+ return SBOX_TEST_FIFTH_ERROR;
+
+ return SBOX_TEST_SUCCEEDED;
+}
+
+TEST(ProcessMitigationsTest, CheckWin8) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+
+ TestRunner runner;
+ sandbox::TargetPolicy* policy = runner.GetPolicy();
+
+ EXPECT_EQ(policy->SetProcessMitigations(
+ MITIGATION_DEP |
+ MITIGATION_DEP_NO_ATL_THUNK |
+ MITIGATION_RELOCATE_IMAGE |
+ MITIGATION_RELOCATE_IMAGE_REQUIRED |
+ MITIGATION_EXTENSION_DLL_DISABLE),
+ SBOX_ALL_OK);
+
+ EXPECT_EQ(policy->SetDelayedProcessMitigations(
+ MITIGATION_STRICT_HANDLE_CHECKS |
+ MITIGATION_WIN32K_DISABLE),
+ SBOX_ALL_OK);
+
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8"));
+}
+
+
+SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) {
+#if !defined(_WIN64) // DEP is always enabled on 64-bit.
+ GetProcessDEPPolicyFunction get_process_dep_policy =
+ reinterpret_cast<GetProcessDEPPolicyFunction>(
+ ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"),
+ "GetProcessDEPPolicy"));
+ if (get_process_dep_policy) {
+ BOOL is_permanent = FALSE;
+ DWORD dep_flags = 0;
+
+ if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags,
+ &is_permanent)) {
+ return SBOX_TEST_FIRST_ERROR;
+ }
+
+ if (!(dep_flags & PROCESS_DEP_ENABLE) || !is_permanent)
+ return SBOX_TEST_SECOND_ERROR;
+
+ } else {
+ NtQueryInformationProcessFunction query_information_process = NULL;
+ ResolveNTFunctionPtr("NtQueryInformationProcess",
+ &query_information_process);
+ if (!query_information_process)
+ return SBOX_TEST_NOT_FOUND;
+
+ ULONG size = 0;
+ ULONG dep_flags = 0;
+ if (!SUCCEEDED(query_information_process(::GetCurrentProcess(),
+ ProcessExecuteFlags, &dep_flags,
+ sizeof(dep_flags), &size))) {
+ return SBOX_TEST_THIRD_ERROR;
+ }
+
+ const int MEM_EXECUTE_OPTION_ENABLE = 1;
+ const int MEM_EXECUTE_OPTION_DISABLE = 2;
+ const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4;
+ const int MEM_EXECUTE_OPTION_PERMANENT = 8;
+ dep_flags &= 0xff;
+
+ if (dep_flags != (MEM_EXECUTE_OPTION_DISABLE |
+ MEM_EXECUTE_OPTION_PERMANENT)) {
+ return SBOX_TEST_FOURTH_ERROR;
+ }
+ }
+#endif
+
+ return SBOX_TEST_SUCCEEDED;
+}
+
+TEST(ProcessMitigationsTest, CheckDep) {
+ if (!IsXPSP2OrLater() || base::win::GetVersion() > base::win::VERSION_WIN7)
+ return;
+
+ TestRunner runner;
+ sandbox::TargetPolicy* policy = runner.GetPolicy();
+
+ EXPECT_EQ(policy->SetProcessMitigations(
+ MITIGATION_DEP |
+ MITIGATION_DEP_NO_ATL_THUNK |
+ MITIGATION_SEHOP),
+ SBOX_ALL_OK);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep"));
+}
+
+} // namespace sandbox
+
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h
index ff487bcc..f0fc2bc 100644
--- a/sandbox/win/src/sandbox_policy.h
+++ b/sandbox/win/src/sandbox_policy.h
@@ -164,6 +164,22 @@ class TargetPolicy {
// Sets a capability to be enabled for the sandboxed process' AppContainer.
virtual ResultCode SetCapability(const wchar_t* sid) = 0;
+ // Sets the mitigations enabled when the process is created. Most of these
+ // are implemented as attributes passed via STARTUPINFOEX. So they take
+ // effect before any thread in the target executes. The declaration of
+ // MitigationFlags is followed by a detailed description of each flag.
+ virtual ResultCode SetProcessMitigations(MitigationFlags flags) = 0;
+
+ // Returns the currently set mitigation flags.
+ virtual MitigationFlags GetProcessMitigations() = 0;
+
+ // Sets process mitigation flags that don't take effect before the call to
+ // LowerToken().
+ virtual ResultCode SetDelayedProcessMitigations(MitigationFlags flags) = 0;
+
+ // Returns the currently set delayed mitigation flags.
+ virtual MitigationFlags GetDelayedProcessMitigations() = 0;
+
// Sets the interceptions to operate in strict mode. By default, interceptions
// are performed in "relaxed" mode, where if something inside NTDLL.DLL is
// already patched we attempt to intercept it anyway. Setting interceptions
diff --git a/sandbox/win/src/sandbox_policy_base.cc b/sandbox/win/src/sandbox_policy_base.cc
index 3950a0c..f942ff5a 100644
--- a/sandbox/win/src/sandbox_policy_base.cc
+++ b/sandbox/win/src/sandbox_policy_base.cc
@@ -15,6 +15,7 @@
#include "sandbox/win/src/handle_policy.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/interception.h"
+#include "sandbox/win/src/process_mitigations.h"
#include "sandbox/win/src/named_pipe_dispatcher.h"
#include "sandbox/win/src/named_pipe_policy.h"
#include "sandbox/win/src/policy_broker.h"
@@ -53,6 +54,7 @@ sandbox::PolicyGlobal* MakeBrokerPolicyMemory() {
namespace sandbox {
SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level;
+SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations;
// Initializes static members.
HWINSTA PolicyBase::alternate_winstation_handle_ = NULL;
@@ -70,6 +72,8 @@ PolicyBase::PolicyBase()
relaxed_interceptions_(true),
integrity_level_(INTEGRITY_LEVEL_LAST),
delayed_integrity_level_(INTEGRITY_LEVEL_LAST),
+ mitigations_(0),
+ delayed_mitigations_(0),
policy_maker_(NULL),
policy_(NULL) {
::InitializeCriticalSection(&lock_);
@@ -276,6 +280,30 @@ ResultCode PolicyBase::SetCapability(const wchar_t* sid) {
return SBOX_ALL_OK;
}
+ResultCode PolicyBase::SetProcessMitigations(
+ MitigationFlags flags) {
+ if (!CanSetProcessMitigationsPreStartup(flags))
+ return SBOX_ERROR_BAD_PARAMS;
+ mitigations_ = flags;
+ return SBOX_ALL_OK;
+}
+
+MitigationFlags PolicyBase::GetProcessMitigations() {
+ return mitigations_;
+}
+
+ResultCode PolicyBase::SetDelayedProcessMitigations(
+ MitigationFlags flags) {
+ if (!CanSetProcessMitigationsPostStartup(flags))
+ return SBOX_ERROR_BAD_PARAMS;
+ delayed_mitigations_ = flags;
+ return SBOX_ALL_OK;
+}
+
+MitigationFlags PolicyBase::GetDelayedProcessMitigations() {
+ return delayed_mitigations_;
+}
+
void PolicyBase::SetStrictInterceptions() {
relaxed_interceptions_ = false;
}
@@ -450,6 +478,11 @@ bool PolicyBase::AddTarget(TargetProcess* target) {
if (NULL != policy_)
policy_maker_->Done();
+ if (!ApplyProcessMitigationsToSuspendedProcess(target->Process(),
+ mitigations_)) {
+ return false;
+ }
+
if (!SetupAllInterceptions(target))
return false;
@@ -469,6 +502,19 @@ bool PolicyBase::AddTarget(TargetProcess* target) {
if (SBOX_ALL_OK != ret)
return false;
+ // Add in delayed mitigations and pseudo-mitigations enforced at startup.
+ g_shared_delayed_mitigations = delayed_mitigations_ |
+ FilterPostStartupProcessMitigations(mitigations_);
+ if (!CanSetProcessMitigationsPostStartup(g_shared_delayed_mitigations))
+ return false;
+
+ 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 false;
+
AutoLock lock(&lock_);
targets_.push_back(target);
return true;
diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h
index 1334304..efac6a0 100644
--- a/sandbox/win/src/sandbox_policy_base.h
+++ b/sandbox/win/src/sandbox_policy_base.h
@@ -52,6 +52,11 @@ class PolicyBase : public Dispatcher, public TargetPolicy {
IntegrityLevel integrity_level) OVERRIDE;
virtual ResultCode SetAppContainer(const wchar_t* sid) OVERRIDE;
virtual ResultCode SetCapability(const wchar_t* sid) OVERRIDE;
+ virtual ResultCode SetProcessMitigations(MitigationFlags flags) OVERRIDE;
+ virtual MitigationFlags GetProcessMitigations() OVERRIDE;
+ virtual ResultCode SetDelayedProcessMitigations(
+ MitigationFlags flags) OVERRIDE;
+ virtual MitigationFlags GetDelayedProcessMitigations() OVERRIDE;
virtual void SetStrictInterceptions() OVERRIDE;
virtual ResultCode AddRule(SubSystem subsystem, Semantics semantics,
const wchar_t* pattern) OVERRIDE;
@@ -120,6 +125,8 @@ class PolicyBase : public Dispatcher, public TargetPolicy {
bool relaxed_interceptions_;
IntegrityLevel integrity_level_;
IntegrityLevel delayed_integrity_level_;
+ MitigationFlags mitigations_;
+ MitigationFlags delayed_mitigations_;
// The array of objects that will answer IPC calls.
Dispatcher* ipc_targets_[IPC_LAST_TAG];
// Object in charge of generating the low level policy.
diff --git a/sandbox/win/src/sandbox_types.h b/sandbox/win/src/sandbox_types.h
index dcf2042..8e9aef2 100644
--- a/sandbox/win/src/sandbox_types.h
+++ b/sandbox/win/src/sandbox_types.h
@@ -43,6 +43,8 @@ enum ResultCode {
SBOX_ERROR_INVALID_CAPABILITY = 15,
// There is a failure initializing the AppContainer.
SBOX_ERROR_CANNOT_INIT_APPCONTAINER = 16,
+ // Initializing or updating ProcThreadAttributes failed.
+ SBOX_ERROR_PROC_THREAD_ATTRIBUTES = 17,
// Placeholder for last item of the enum.
SBOX_ERROR_LAST
};
@@ -54,7 +56,8 @@ enum TerminationCodes {
SBOX_FATAL_DROPTOKEN = 7007, // Could not lower the token.
SBOX_FATAL_FLUSHANDLES = 7008, // Failed to flush registry handles.
SBOX_FATAL_CACHEDISABLE = 7009, // Failed to forbid HCKU caching.
- SBOX_FATAL_CLOSEHANDLES = 7010 // Failed to close pending handles.
+ SBOX_FATAL_CLOSEHANDLES = 7010, // Failed to close pending handles.
+ SBOX_FATAL_MITIGATION = 7011 // Could not set the mitigation policy.
};
class BrokerServices;
diff --git a/sandbox/win/src/security_level.h b/sandbox/win/src/security_level.h
index 467f96f..766293d 100644
--- a/sandbox/win/src/security_level.h
+++ b/sandbox/win/src/security_level.h
@@ -122,6 +122,64 @@ enum JobLevel {
JOB_UNPROTECTED
};
+// These flags correspond to various process-level mitigations (eg. ASLR and
+// DEP). Most are implemented via UpdateProcThreadAttribute() plus flags for
+// the PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY attribute argument; documented
+// here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686880
+// Some mitigations are implemented directly by the sandbox or emulated to
+// the greatest extent possible when not directly supported by the OS.
+// Flags that are unsupported for the target OS will be silently ignored.
+// Flags that are invalid for their application (pre or post startup) will
+// return SBOX_ERROR_BAD_PARAMS.
+typedef uint64 MitigationFlags;
+// Permanently enables DEP for the target process. Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE.
+const MitigationFlags MITIGATION_DEP = 0x00000001;
+// Permanently Disables ATL thunk emulation when DEP is enabled. Valid
+// only when MITIGATION_DEP is passed. Corresponds to not passing
+// PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE.
+const MitigationFlags MITIGATION_DEP_NO_ATL_THUNK = 0x00000002;
+// Enables Structured exception handling override prevention. Must be
+// enabled prior to process start. Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE.
+const MitigationFlags MITIGATION_SEHOP = 0x00000004;
+// Forces ASLR on all images in the child process. Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON .
+const MitigationFlags MITIGATION_RELOCATE_IMAGE = 0x00000008;
+// Refuses to load DLLs that cannot support ASLR. Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON_REQ_RELOCS.
+const MitigationFlags MITIGATION_RELOCATE_IMAGE_REQUIRED = 0x00000010;
+// Terminates the process on Windows heap corruption. Coresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_HEAP_TERMINATE_ALWAYS_ON.
+const MitigationFlags MITIGATION_HEAP_TERMINATE = 0x00000020;
+// Sets a random lower bound as the minimum user address. Must be
+// enabled prior to process start. On 32-bit processes this is
+// emulated to a much smaller degree. Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_ON.
+const MitigationFlags MITIGATION_BOTTOM_UP_ASLR = 0x00000040;
+// Increases the randomness range of bottom-up ASLR to up to 1TB. Must be
+// enabled prior to process start and with MITIGATION_BOTTOM_UP_ASLR.
+// Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_HIGH_ENTROPY_ASLR_ALWAYS_ON
+const MitigationFlags MITIGATION_HIGH_ENTROPY_ASLR = 0x00000080;
+// Immediately raises an exception on a bad handle reference. Must be
+// enabled after startup. Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON.
+const MitigationFlags MITIGATION_STRICT_HANDLE_CHECKS = 0x00000100;
+// Prevents the process from making Win32k calls. Must be enabled after
+// startup. Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON.
+const MitigationFlags MITIGATION_WIN32K_DISABLE = 0x00000200;
+// Disables common DLL injection methods (e.g. window hooks and
+// App_InitDLLs). Corresponds to
+// PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON.
+const MitigationFlags MITIGATION_EXTENSION_DLL_DISABLE = 0x00000400;
+// Sets the DLL search order to LOAD_LIBRARY_SEARCH_DEFAULT_DIRS. Additional
+// directories can be added via the Windows AddDllDirectory() function.
+// http://msdn.microsoft.com/en-us/library/windows/desktop/hh310515
+// Must be enabled after startup.
+const MitigationFlags MITIGATION_DLL_SEARCH_ORDER = 0x00000001ULL << 32;
+
} // namespace sandbox
#endif // SANDBOX_SRC_SECURITY_LEVEL_H_
diff --git a/sandbox/win/src/target_process.cc b/sandbox/win/src/target_process.cc
index 164b2a9..4eea180 100644
--- a/sandbox/win/src/target_process.cc
+++ b/sandbox/win/src/target_process.cc
@@ -35,27 +35,6 @@ void CopyPolicyToTarget(const void* source, size_t size, void* dest) {
}
}
-// Reserve a random range at the bottom of the address space in the target
-// process to prevent predictable alocations at low addresses.
-void PoisonLowerAddressRange(HANDLE process) {
- unsigned int limit;
- rand_s(&limit);
- char* ptr = 0;
- const size_t kMask64k = 0xFFFF;
- // Random range (512k-16.5mb) in 64k steps.
- const char* end = ptr + ((((limit % 16384) + 512) * 1024) & ~kMask64k);
- while (ptr < end) {
- MEMORY_BASIC_INFORMATION memory_info;
- if (!::VirtualQueryEx(process, ptr, &memory_info, sizeof(memory_info)))
- break;
- size_t size = std::min((memory_info.RegionSize + kMask64k) & ~kMask64k,
- static_cast<SIZE_T>(end - ptr));
- if (ptr && memory_info.State == MEM_FREE)
- ::VirtualAllocEx(process, ptr, size, MEM_RESERVE, PAGE_NOACCESS);
- ptr += size;
- }
-}
-
}
namespace sandbox {
@@ -168,8 +147,6 @@ DWORD TargetProcess::Create(const wchar_t* exe_path,
}
lockdown_token_.Close();
- PoisonLowerAddressRange(process_info.process_handle());
-
DWORD win_result = ERROR_SUCCESS;
// Assign the suspended target to the windows job object.
diff --git a/sandbox/win/src/target_services.cc b/sandbox/win/src/target_services.cc
index 495f108..03813c8 100644
--- a/sandbox/win/src/target_services.cc
+++ b/sandbox/win/src/target_services.cc
@@ -11,6 +11,7 @@
#include "sandbox/win/src/handle_closer_agent.h"
#include "sandbox/win/src/handle_interception.h"
#include "sandbox/win/src/ipc_tags.h"
+#include "sandbox/win/src/process_mitigations.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_types.h"
@@ -61,6 +62,7 @@ namespace sandbox {
SANDBOX_INTERCEPT IntegrityLevel g_shared_delayed_integrity_level =
INTEGRITY_LEVEL_LAST;
+SANDBOX_INTERCEPT MitigationFlags g_shared_delayed_mitigations = 0;
TargetServicesBase::TargetServicesBase() {
}
@@ -86,6 +88,10 @@ void TargetServicesBase::LowerToken() {
::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CACHEDISABLE);
if (!CloseOpenHandles())
::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CLOSEHANDLES);
+ // Enabling mitigations must happen last otherwise handle closing breaks
+ if (g_shared_delayed_mitigations &&
+ !ApplyProcessMitigationsToCurrentProcess(g_shared_delayed_mitigations))
+ ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_MITIGATION);
}
ProcessState* TargetServicesBase::GetState() {
diff --git a/sandbox/win/tests/common/controller.h b/sandbox/win/tests/common/controller.h
index fd7a833..3d42878 100644
--- a/sandbox/win/tests/common/controller.h
+++ b/sandbox/win/tests/common/controller.h
@@ -31,6 +31,10 @@ enum SboxTestResult {
SBOX_TEST_FIRST_ERROR = SBOX_TEST_FIRST_RESULT | SEVERITY_ERROR_FLAGS,
SBOX_TEST_SECOND_ERROR,
SBOX_TEST_THIRD_ERROR,
+ SBOX_TEST_FOURTH_ERROR,
+ SBOX_TEST_FIFTH_ERROR,
+ SBOX_TEST_SIXTH_ERROR,
+ SBOX_TEST_SEVENTH_ERROR,
SBOX_TEST_INVALID_PARAMETER,
SBOX_TEST_FAILED_TO_RUN_TEST,
SBOX_TEST_FAILED_TO_EXECUTE_COMMAND,