Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(784)

Unified Diff: sandbox/win/src/process_mitigations.cc

Issue 10690058: Add sandbox support for Windows process mitigations (Closed) Base URL: https://src.chromium.org/svn/trunk/src/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sandbox/win/src/process_mitigations.cc
===================================================================
--- sandbox/win/src/process_mitigations.cc (revision 0)
+++ sandbox/win/src/process_mitigations.cc (revision 0)
@@ -0,0 +1,297 @@
+// 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_policy.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 SetProcessMitigationsForCurrentProcess(uint64 flags) {
+ if (!CanSetProcessMitigationsPostStartup(flags))
+ return false;
+
+ HMODULE module = ::GetModuleHandleA("kernel32.dll");
+
+ // We can't apply anything before Win XP, so just return cleanly.
+ if (!IsXPSP2OrLater())
rvargas (doing something else) 2012/09/08 02:23:32 nit: bail out before line 34.
jschuh 2012/09/10 23:58:48 Done.
+ return true;
+
+ if (flags & TargetPolicy::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 & TargetPolicy::MITIGATION_HEAP_TERMINATE) {
+ if (!::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption,
+ NULL, 0))
+ return false;
+ }
+
+#ifndef _WIN64 // DEP is always enabled on 64-bit.
rvargas (doing something else) 2012/09/08 02:23:32 nit: #if !defined
jschuh 2012/09/10 23:58:48 Done.
+ if (flags & TargetPolicy::MITIGATION_DEP) {
+ DWORD dep_flags = PROCESS_DEP_ENABLE;
+
+ if (flags & TargetPolicy::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 & TargetPolicy::MITIGATION_RELOCATE_IMAGE) {
+ PROCESS_MITIGATION_ASLR_POLICY policy = { 0 };
+ policy.EnableForceRelocateImages = true;
+ policy.DisallowStrippedImages = (flags &
+ TargetPolicy::MITIGATION_RELOCATE_IMAGE_REQUIRED) ==
+ TargetPolicy::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 & TargetPolicy::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 & TargetPolicy::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 & TargetPolicy::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;
+}
+
+DWORD64 GetProcessMitigationPolicyFlags(uint64 flags) {
+ base::win::Version version = base::win::GetVersion();
+
+ // Nothing for Win XP.
+ if (version < base::win::VERSION_VISTA)
+ return 0;
+
+ DWORD64 real_flags = 0;
+ if (flags & TargetPolicy::MITIGATION_DEP) {
+ real_flags |= PROCESS_CREATION_MITIGATION_POLICY_DEP_ENABLE;
+ if (!(flags & TargetPolicy::MITIGATION_DEP_NO_ATL_THUNK))
+ real_flags |= PROCESS_CREATION_MITIGATION_POLICY_DEP_ATL_THUNK_ENABLE;
+ }
+
+ if (flags & TargetPolicy::MITIGATION_SEHOP)
+ real_flags |= PROCESS_CREATION_MITIGATION_POLICY_SEHOP_ENABLE;
+
+ // Win 7 and Vista
+ if (version < base::win::VERSION_WIN8)
+ return real_flags;
+
+ if (flags & TargetPolicy::MITIGATION_RELOCATE_IMAGE) {
+ real_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON;
+ if (flags & TargetPolicy::MITIGATION_RELOCATE_IMAGE_REQUIRED) {
+ real_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_ON_REQ_RELOCS;
+ }
+ }
+
+ if (flags & TargetPolicy::MITIGATION_HEAP_TERMINATE)
+ real_flags |= PROCESS_CREATION_MITIGATION_POLICY_HEAP_TERMINATE_ALWAYS_ON;
+
+ if (flags & TargetPolicy::MITIGATION_BOTTOM_UP_ASLR)
+ real_flags |= PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_ON;
+
+ if (flags & TargetPolicy::MITIGATION_HIGH_ENTROPY_ASLR) {
+ real_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_HIGH_ENTROPY_ASLR_ALWAYS_ON;
+ }
+
+ if (flags & TargetPolicy::MITIGATION_STRICT_HANDLE_CHECKS) {
+ real_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON;
+ }
+
+ if (flags & TargetPolicy::MITIGATION_WIN32K_DISABLE) {
+ real_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON;
+ }
+
+ if (flags & TargetPolicy::MITIGATION_EXTENSION_DLL_DISABLE) {
+ real_flags |=
+ PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON;
+ }
+
+ // Windows 8.
rvargas (doing something else) 2012/09/08 02:23:32 nit: redundant comment?
jschuh 2012/09/10 23:58:48 Done.
+ return real_flags;
+}
+
+uint64 GetPostStartupProcessMitigations(uint64 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 & (TargetPolicy::MITIGATION_DEP |
+ TargetPolicy::MITIGATION_DEP_NO_ATL_THUNK);
+
+ // Windows 7 and Vista.
+ } else if (version < base::win::VERSION_WIN8) {
+ return flags & (TargetPolicy::MITIGATION_BOTTOM_UP_ASLR |
+ TargetPolicy::MITIGATION_DLL_SEARCH_ORDER |
+ TargetPolicy::MITIGATION_HEAP_TERMINATE);
+ }
+
+ // Windows 8 and above.
+ return flags & (TargetPolicy::MITIGATION_BOTTOM_UP_ASLR |
+ TargetPolicy::MITIGATION_DLL_SEARCH_ORDER);
+}
+
+bool SetProcessMitigationsForSuspendedProcess(HANDLE process, uint64 flags) {
+// This is a hack to fake a weak bottom-up ASLR on 32-bit Windows.
+#ifndef _WIN64
rvargas (doing something else) 2012/09/08 02:23:32 ditto
jschuh 2012/09/10 23:58:48 Done.
+ if (flags & TargetPolicy::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(uint64 flags) {
+ // All of these mitigations can be enabled after startup.
+ return !(flags & ~(TargetPolicy::MITIGATION_HEAP_TERMINATE |
+ TargetPolicy::MITIGATION_DEP |
+ TargetPolicy::MITIGATION_DEP_NO_ATL_THUNK |
+ TargetPolicy::MITIGATION_RELOCATE_IMAGE |
+ TargetPolicy::MITIGATION_RELOCATE_IMAGE_REQUIRED |
+ TargetPolicy::MITIGATION_BOTTOM_UP_ASLR |
+ TargetPolicy::MITIGATION_STRICT_HANDLE_CHECKS |
+ TargetPolicy::MITIGATION_WIN32K_DISABLE |
+ TargetPolicy::MITIGATION_EXTENSION_DLL_DISABLE));
+}
+
+bool CanSetProcessMitigationsPreStartup(uint64 flags) {
+ // These mitigations cannot be enabled prior to startup.
+ return !(flags & (TargetPolicy::MITIGATION_STRICT_HANDLE_CHECKS |
+ TargetPolicy::MITIGATION_WIN32K_DISABLE |
+ TargetPolicy::MITIGATION_DLL_SEARCH_ORDER));
+}
+
+} // namespace sandbox
+

Powered by Google App Engine
This is Rietveld 408576698