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/sandbox_utils.h" 14 #include "sandbox/win/src/target_services.h" 15 #include "sandbox/win/src/win_utils.h" 16 #include "sandbox/win/tests/common/controller.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 namespace { 20 21 typedef BOOL (WINAPI *GetProcessDEPPolicyFunction)( 22 HANDLE process, 23 LPDWORD flags, 24 PBOOL permanent); 25 26 typedef BOOL (WINAPI *GetProcessMitigationPolicyFunction)( 27 HANDLE process, 28 PROCESS_MITIGATION_POLICY mitigation_policy, 29 PVOID buffer, 30 SIZE_T length); 31 32 GetProcessMitigationPolicyFunction get_process_mitigation_policy; 33 34 bool CheckWin8DepPolicy() { 35 PROCESS_MITIGATION_DEP_POLICY policy; 36 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, 37 &policy, sizeof(policy))) { 38 return false; 39 } 40 return policy.Enable && policy.Permanent; 41 } 42 43 bool CheckWin8AslrPolicy() { 44 PROCESS_MITIGATION_ASLR_POLICY policy; 45 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy, 46 &policy, sizeof(policy))) { 47 return false; 48 } 49 return policy.EnableForceRelocateImages && policy.DisallowStrippedImages; 50 } 51 52 bool CheckWin8StrictHandlePolicy() { 53 PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy; 54 if (!get_process_mitigation_policy(::GetCurrentProcess(), 55 ProcessStrictHandleCheckPolicy, 56 &policy, sizeof(policy))) { 57 return false; 58 } 59 return policy.RaiseExceptionOnInvalidHandleReference && 60 policy.HandleExceptionsPermanentlyEnabled; 61 } 62 63 bool CheckWin8Win32CallPolicy() { 64 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy; 65 if (!get_process_mitigation_policy(::GetCurrentProcess(), 66 ProcessSystemCallDisablePolicy, 67 &policy, sizeof(policy))) { 68 return false; 69 } 70 return policy.DisallowWin32kSystemCalls; 71 } 72 73 bool CheckWin8DllExtensionPolicy() { 74 PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy; 75 if (!get_process_mitigation_policy(::GetCurrentProcess(), 76 ProcessExtensionPointDisablePolicy, 77 &policy, sizeof(policy))) { 78 return false; 79 } 80 return policy.DisableExtensionPoints; 81 } 82 83 } // namespace 84 85 namespace sandbox { 86 87 SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { 88 get_process_mitigation_policy = 89 reinterpret_cast<GetProcessMitigationPolicyFunction>( 90 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), 91 "GetProcessMitigationPolicy")); 92 93 if (!get_process_mitigation_policy) 94 return SBOX_TEST_NOT_FOUND; 95 96 if (!CheckWin8DepPolicy()) 97 return SBOX_TEST_FIRST_ERROR; 98 99 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. 100 if (!CheckWin8AslrPolicy()) 101 return SBOX_TEST_SECOND_ERROR; 102 #endif 103 104 if (!CheckWin8StrictHandlePolicy()) 105 return SBOX_TEST_THIRD_ERROR; 106 107 if (!CheckWin8Win32CallPolicy()) 108 return SBOX_TEST_FOURTH_ERROR; 109 110 if (!CheckWin8DllExtensionPolicy()) 111 return SBOX_TEST_FIFTH_ERROR; 112 113 return SBOX_TEST_SUCCEEDED; 114 } 115 116 TEST(ProcessMitigationsTest, CheckWin8) { 117 if (base::win::GetVersion() < base::win::VERSION_WIN8) 118 return; 119 120 TestRunner runner; 121 sandbox::TargetPolicy* policy = runner.GetPolicy(); 122 123 sandbox::MitigationFlags mitigations = MITIGATION_DEP | 124 MITIGATION_DEP_NO_ATL_THUNK | 125 MITIGATION_EXTENSION_DLL_DISABLE; 126 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. 127 mitigations |= MITIGATION_RELOCATE_IMAGE | 128 MITIGATION_RELOCATE_IMAGE_REQUIRED; 129 #endif 130 131 EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); 132 133 mitigations |= MITIGATION_STRICT_HANDLE_CHECKS | 134 MITIGATION_WIN32K_DISABLE; 135 136 EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); 137 138 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8")); 139 } 140 141 142 SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t **argv) { 143 GetProcessDEPPolicyFunction get_process_dep_policy = 144 reinterpret_cast<GetProcessDEPPolicyFunction>( 145 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), 146 "GetProcessDEPPolicy")); 147 if (get_process_dep_policy) { 148 BOOL is_permanent = FALSE; 149 DWORD dep_flags = 0; 150 151 if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags, 152 &is_permanent)) { 153 return SBOX_TEST_FIRST_ERROR; 154 } 155 156 if (!(dep_flags & PROCESS_DEP_ENABLE) || !is_permanent) 157 return SBOX_TEST_SECOND_ERROR; 158 159 } else { 160 NtQueryInformationProcessFunction query_information_process = NULL; 161 ResolveNTFunctionPtr("NtQueryInformationProcess", 162 &query_information_process); 163 if (!query_information_process) 164 return SBOX_TEST_NOT_FOUND; 165 166 ULONG size = 0; 167 ULONG dep_flags = 0; 168 if (!SUCCEEDED(query_information_process(::GetCurrentProcess(), 169 ProcessExecuteFlags, &dep_flags, 170 sizeof(dep_flags), &size))) { 171 return SBOX_TEST_THIRD_ERROR; 172 } 173 174 const int MEM_EXECUTE_OPTION_ENABLE = 1; 175 const int MEM_EXECUTE_OPTION_DISABLE = 2; 176 const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4; 177 const int MEM_EXECUTE_OPTION_PERMANENT = 8; 178 dep_flags &= 0xff; 179 180 if (dep_flags != (MEM_EXECUTE_OPTION_DISABLE | 181 MEM_EXECUTE_OPTION_PERMANENT)) { 182 return SBOX_TEST_FOURTH_ERROR; 183 } 184 } 185 186 return SBOX_TEST_SUCCEEDED; 187 } 188 189 #if !defined(_WIN64) // DEP is always enabled on 64-bit. 190 TEST(ProcessMitigationsTest, CheckDep) { 191 if (!IsXPSP2OrLater() || base::win::GetVersion() > base::win::VERSION_WIN7) 192 return; 193 194 TestRunner runner; 195 sandbox::TargetPolicy* policy = runner.GetPolicy(); 196 197 EXPECT_EQ(policy->SetProcessMitigations( 198 MITIGATION_DEP | 199 MITIGATION_DEP_NO_ATL_THUNK | 200 MITIGATION_SEHOP), 201 SBOX_ALL_OK); 202 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep")); 203 } 204 #endif 205 206 } // namespace sandbox 207 208