1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/strings/stringprintf.h" 6#include "base/win/scoped_handle.h" 7 8#include "base/win/windows_version.h" 9#include "sandbox/win/src/nt_internals.h" 10#include "sandbox/win/src/process_mitigations.h" 11#include "sandbox/win/src/sandbox.h" 12#include "sandbox/win/src/sandbox_factory.h" 13#include "sandbox/win/src/target_services.h" 14#include "sandbox/win/src/win_utils.h" 15#include "sandbox/win/tests/common/controller.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18namespace { 19 20typedef BOOL (WINAPI *GetProcessDEPPolicyFunction)( 21 HANDLE process, 22 LPDWORD flags, 23 PBOOL permanent); 24 25typedef BOOL (WINAPI *GetProcessMitigationPolicyFunction)( 26 HANDLE process, 27 PROCESS_MITIGATION_POLICY mitigation_policy, 28 PVOID buffer, 29 SIZE_T length); 30 31GetProcessMitigationPolicyFunction get_process_mitigation_policy; 32 33bool CheckWin8DepPolicy() { 34 PROCESS_MITIGATION_DEP_POLICY policy; 35 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, 36 &policy, sizeof(policy))) { 37 return false; 38 } 39 return policy.Enable && policy.Permanent; 40} 41 42bool CheckWin8AslrPolicy() { 43 PROCESS_MITIGATION_ASLR_POLICY policy; 44 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy, 45 &policy, sizeof(policy))) { 46 return false; 47 } 48 return policy.EnableForceRelocateImages && policy.DisallowStrippedImages; 49} 50 51bool CheckWin8StrictHandlePolicy() { 52 PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy; 53 if (!get_process_mitigation_policy(::GetCurrentProcess(), 54 ProcessStrictHandleCheckPolicy, 55 &policy, sizeof(policy))) { 56 return false; 57 } 58 return policy.RaiseExceptionOnInvalidHandleReference && 59 policy.HandleExceptionsPermanentlyEnabled; 60} 61 62bool CheckWin8Win32CallPolicy() { 63 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy; 64 if (!get_process_mitigation_policy(::GetCurrentProcess(), 65 ProcessSystemCallDisablePolicy, 66 &policy, sizeof(policy))) { 67 return false; 68 } 69 return policy.DisallowWin32kSystemCalls; 70} 71 72bool CheckWin8DllExtensionPolicy() { 73 PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy; 74 if (!get_process_mitigation_policy(::GetCurrentProcess(), 75 ProcessExtensionPointDisablePolicy, 76 &policy, sizeof(policy))) { 77 return false; 78 } 79 return policy.DisableExtensionPoints; 80} 81 82} // namespace 83 84namespace sandbox { 85 86SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { 87 get_process_mitigation_policy = 88 reinterpret_cast<GetProcessMitigationPolicyFunction>( 89 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), 90 "GetProcessMitigationPolicy")); 91 if (!get_process_mitigation_policy) 92 return SBOX_TEST_NOT_FOUND; 93 94 if (!CheckWin8DepPolicy()) 95 return SBOX_TEST_FIRST_ERROR; 96 97#if defined(NDEBUG) // ASLR cannot be forced in debug builds. 98 if (!CheckWin8AslrPolicy()) 99 return SBOX_TEST_SECOND_ERROR; 100#endif 101 102 if (!CheckWin8StrictHandlePolicy()) 103 return SBOX_TEST_THIRD_ERROR; 104 105 if (!CheckWin8DllExtensionPolicy()) 106 return SBOX_TEST_FIFTH_ERROR; 107 108 return SBOX_TEST_SUCCEEDED; 109} 110 111TEST(ProcessMitigationsTest, CheckWin8) { 112 if (base::win::GetVersion() < base::win::VERSION_WIN8) 113 return; 114 115 TestRunner runner; 116 sandbox::TargetPolicy* policy = runner.GetPolicy(); 117 118 sandbox::MitigationFlags mitigations = MITIGATION_DEP | 119 MITIGATION_DEP_NO_ATL_THUNK | 120 MITIGATION_EXTENSION_DLL_DISABLE; 121#if defined(NDEBUG) // ASLR cannot be forced in debug builds. 122 mitigations |= MITIGATION_RELOCATE_IMAGE | 123 MITIGATION_RELOCATE_IMAGE_REQUIRED; 124#endif 125 126 EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); 127 128 mitigations |= MITIGATION_STRICT_HANDLE_CHECKS; 129 130 EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); 131 132 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8")); 133} 134 135 136SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) { 137 GetProcessDEPPolicyFunction get_process_dep_policy = 138 reinterpret_cast<GetProcessDEPPolicyFunction>( 139 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), 140 "GetProcessDEPPolicy")); 141 if (get_process_dep_policy) { 142 BOOL is_permanent = FALSE; 143 DWORD dep_flags = 0; 144 145 if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags, 146 &is_permanent)) { 147 return SBOX_TEST_FIRST_ERROR; 148 } 149 150 if (!(dep_flags & PROCESS_DEP_ENABLE) || !is_permanent) 151 return SBOX_TEST_SECOND_ERROR; 152 153 } else { 154 NtQueryInformationProcessFunction query_information_process = NULL; 155 ResolveNTFunctionPtr("NtQueryInformationProcess", 156 &query_information_process); 157 if (!query_information_process) 158 return SBOX_TEST_NOT_FOUND; 159 160 ULONG size = 0; 161 ULONG dep_flags = 0; 162 if (!SUCCEEDED(query_information_process(::GetCurrentProcess(), 163 ProcessExecuteFlags, &dep_flags, 164 sizeof(dep_flags), &size))) { 165 return SBOX_TEST_THIRD_ERROR; 166 } 167 168 const int MEM_EXECUTE_OPTION_ENABLE = 1; 169 const int MEM_EXECUTE_OPTION_DISABLE = 2; 170 const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4; 171 const int MEM_EXECUTE_OPTION_PERMANENT = 8; 172 dep_flags &= 0xff; 173 174 if (dep_flags != (MEM_EXECUTE_OPTION_DISABLE | 175 MEM_EXECUTE_OPTION_PERMANENT)) { 176 return SBOX_TEST_FOURTH_ERROR; 177 } 178 } 179 180 return SBOX_TEST_SUCCEEDED; 181} 182 183#if !defined(_WIN64) // DEP is always enabled on 64-bit. 184TEST(ProcessMitigationsTest, CheckDep) { 185 if (base::win::GetVersion() > base::win::VERSION_WIN7) 186 return; 187 188 TestRunner runner; 189 sandbox::TargetPolicy* policy = runner.GetPolicy(); 190 191 EXPECT_EQ(policy->SetProcessMitigations( 192 MITIGATION_DEP | 193 MITIGATION_DEP_NO_ATL_THUNK | 194 MITIGATION_SEHOP), 195 SBOX_ALL_OK); 196 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep")); 197} 198#endif 199 200SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t **argv) { 201 get_process_mitigation_policy = 202 reinterpret_cast<GetProcessMitigationPolicyFunction>( 203 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), 204 "GetProcessMitigationPolicy")); 205 if (!get_process_mitigation_policy) 206 return SBOX_TEST_NOT_FOUND; 207 208 if (!CheckWin8Win32CallPolicy()) 209 return SBOX_TEST_FIRST_ERROR; 210 return SBOX_TEST_SUCCEEDED; 211} 212 213// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation on 214// the target process causes the launch to fail in process initialization. 215// The test process itself links against user32/gdi32. 216TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownFailure) { 217 if (base::win::GetVersion() < base::win::VERSION_WIN8) 218 return; 219 220 TestRunner runner; 221 sandbox::TargetPolicy* policy = runner.GetPolicy(); 222 223 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), 224 SBOX_ALL_OK); 225 EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); 226} 227 228// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation 229// along with the policy to fake user32 and gdi32 initialization successfully 230// launches the target process. 231// The test process itself links against user32/gdi32. 232TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownSuccess) { 233 if (base::win::GetVersion() < base::win::VERSION_WIN8) 234 return; 235 236 TestRunner runner; 237 sandbox::TargetPolicy* policy = runner.GetPolicy(); 238 239 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), 240 SBOX_ALL_OK); 241 EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, 242 sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL), 243 sandbox::SBOX_ALL_OK); 244 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); 245} 246 247} // namespace sandbox 248 249