Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/win/src/process_mitigations.h" | |
| 6 | |
| 7 #include <psapi.h> | |
| 8 | |
| 9 #include <chrono> | |
| 10 #include <thread> | |
|
dcheng
2016/04/03 23:30:01
Btw, I hate to the bearer of bad news but both <ch
Will Harris
2016/04/04 00:16:41
yes I noticed that too, suggested using base::Plat
penny
2016/04/11 22:11:58
Done.
| |
| 11 | |
| 12 #include "base/command_line.h" | |
| 5 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 6 #include "base/files/scoped_temp_dir.h" | 14 #include "base/files/scoped_temp_dir.h" |
| 15 #include "base/memory/free_deleter.h" | |
| 7 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/path_service.h" | 17 #include "base/path_service.h" |
| 9 #include "base/process/launch.h" | 18 #include "base/process/launch.h" |
| 10 #include "base/strings/stringprintf.h" | 19 #include "base/win/registry.h" |
| 11 #include "base/win/scoped_handle.h" | 20 #include "base/win/scoped_handle.h" |
| 21 #include "base/win/startup_information.h" | |
| 22 #include "base/win/win_util.h" | |
| 12 #include "base/win/windows_version.h" | 23 #include "base/win/windows_version.h" |
| 13 #include "sandbox/win/src/nt_internals.h" | 24 #include "sandbox/win/src/nt_internals.h" |
| 14 #include "sandbox/win/src/process_mitigations.h" | |
| 15 #include "sandbox/win/src/sandbox.h" | 25 #include "sandbox/win/src/sandbox.h" |
| 16 #include "sandbox/win/src/sandbox_factory.h" | 26 #include "sandbox/win/src/sandbox_factory.h" |
| 17 #include "sandbox/win/src/target_services.h" | 27 #include "sandbox/win/src/target_services.h" |
| 18 #include "sandbox/win/src/win_utils.h" | |
| 19 #include "sandbox/win/tests/common/controller.h" | 28 #include "sandbox/win/tests/common/controller.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
| 21 | 30 |
| 22 namespace { | 31 namespace { |
| 23 | 32 |
| 24 // API defined in winbase.h. | 33 // API defined in winbase.h. |
| 25 typedef decltype(GetProcessDEPPolicy)* GetProcessDEPPolicyFunction; | 34 typedef decltype(GetProcessDEPPolicy)* GetProcessDEPPolicyFunction; |
| 26 | 35 |
| 27 // API defined in processthreadsapi.h. | 36 // API defined in processthreadsapi.h. |
| 28 typedef decltype( | 37 typedef decltype( |
| 29 GetProcessMitigationPolicy)* GetProcessMitigationPolicyFunction; | 38 GetProcessMitigationPolicy)* GetProcessMitigationPolicyFunction; |
| 30 GetProcessMitigationPolicyFunction get_process_mitigation_policy; | 39 GetProcessMitigationPolicyFunction get_process_mitigation_policy; |
| 31 | 40 |
| 32 // APIs defined in wingdi.h. | 41 // APIs defined in wingdi.h. |
| 33 typedef decltype(AddFontMemResourceEx)* AddFontMemResourceExFunction; | 42 typedef decltype(AddFontMemResourceEx)* AddFontMemResourceExFunction; |
| 34 typedef decltype(RemoveFontMemResourceEx)* RemoveFontMemResourceExFunction; | 43 typedef decltype(RemoveFontMemResourceEx)* RemoveFontMemResourceExFunction; |
| 35 | 44 |
| 45 // WinProc event name for synchronization. | |
| 46 const wchar_t* winproc_event = L"ChromeExtensionTestEvent"; | |
| 47 DWORD event_max_wait_ms = 3 * 1000; | |
| 48 | |
| 36 #if !defined(_WIN64) | 49 #if !defined(_WIN64) |
| 37 bool CheckWin8DepPolicy() { | 50 bool CheckWin8DepPolicy() { |
| 38 PROCESS_MITIGATION_DEP_POLICY policy = {}; | 51 PROCESS_MITIGATION_DEP_POLICY policy = {}; |
| 39 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, | 52 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, |
| 40 &policy, sizeof(policy))) { | 53 &policy, sizeof(policy))) { |
| 41 return false; | 54 return false; |
| 42 } | 55 } |
| 43 return policy.Enable && policy.Permanent; | 56 return policy.Enable && policy.Permanent; |
| 44 } | 57 } |
| 45 #endif // !defined(_WIN64) | 58 #endif // !defined(_WIN64) |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 69 bool CheckWin8Win32CallPolicy() { | 82 bool CheckWin8Win32CallPolicy() { |
| 70 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; | 83 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; |
| 71 if (!get_process_mitigation_policy(::GetCurrentProcess(), | 84 if (!get_process_mitigation_policy(::GetCurrentProcess(), |
| 72 ProcessSystemCallDisablePolicy, | 85 ProcessSystemCallDisablePolicy, |
| 73 &policy, sizeof(policy))) { | 86 &policy, sizeof(policy))) { |
| 74 return false; | 87 return false; |
| 75 } | 88 } |
| 76 return policy.DisallowWin32kSystemCalls; | 89 return policy.DisallowWin32kSystemCalls; |
| 77 } | 90 } |
| 78 | 91 |
| 79 bool CheckWin8DllExtensionPolicy() { | 92 bool CheckWin8ExtensionPointPolicy() { |
| 80 PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; | 93 PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; |
| 81 if (!get_process_mitigation_policy(::GetCurrentProcess(), | 94 if (!get_process_mitigation_policy(::GetCurrentProcess(), |
| 82 ProcessExtensionPointDisablePolicy, | 95 ProcessExtensionPointDisablePolicy, |
| 83 &policy, sizeof(policy))) { | 96 &policy, sizeof(policy))) { |
| 84 return false; | 97 return false; |
| 85 } | 98 } |
| 86 return policy.DisableExtensionPoints; | 99 return policy.DisableExtensionPoints; |
| 87 } | 100 } |
| 88 | 101 |
| 89 bool CheckWin10FontPolicy() { | 102 bool CheckWin10FontPolicy() { |
| 90 PROCESS_MITIGATION_FONT_DISABLE_POLICY policy = {}; | 103 PROCESS_MITIGATION_FONT_DISABLE_POLICY policy = {}; |
| 91 if (!get_process_mitigation_policy(::GetCurrentProcess(), | 104 if (!get_process_mitigation_policy(::GetCurrentProcess(), |
| 92 ProcessFontDisablePolicy, &policy, | 105 ProcessFontDisablePolicy, &policy, |
| 93 sizeof(policy))) { | 106 sizeof(policy))) { |
| 94 return false; | 107 return false; |
| 95 } | 108 } |
| 96 return policy.DisableNonSystemFonts; | 109 return policy.DisableNonSystemFonts; |
| 97 } | 110 } |
| 98 | 111 |
| 99 bool CheckWin10ImageLoadNoRemotePolicy() { | 112 bool CheckWin10ImageLoadNoRemotePolicy() { |
| 100 PROCESS_MITIGATION_IMAGE_LOAD_POLICY policy = {}; | 113 PROCESS_MITIGATION_IMAGE_LOAD_POLICY policy = {}; |
| 101 if (!get_process_mitigation_policy(::GetCurrentProcess(), | 114 if (!get_process_mitigation_policy(::GetCurrentProcess(), |
| 102 ProcessImageLoadPolicy, &policy, | 115 ProcessImageLoadPolicy, &policy, |
| 103 sizeof(policy))) { | 116 sizeof(policy))) { |
| 104 return false; | 117 return false; |
| 105 } | 118 } |
| 106 return policy.NoRemoteImages; | 119 return policy.NoRemoteImages; |
| 107 } | 120 } |
| 108 | 121 |
| 122 // Spawn our Windows process (with or without mitigation enabled). | |
|
Will Harris
2016/04/04 00:15:08
style nit, feel free to ignore, but prefer not to
penny
2016/04/11 22:11:59
Done.
| |
| 123 void SpawnWinProc(PROCESS_INFORMATION* pi, bool success_test, HANDLE* event) { | |
| 124 base::win::StartupInformation startup_info; | |
| 125 DWORD creation_flags = 0; | |
| 126 | |
| 127 if (!success_test) { | |
| 128 DWORD64 flags = | |
| 129 PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; | |
| 130 // This test only runs on >= Win8, so I don't have to worry about | |
| 131 // illegal 64-bit flags on 32-bit <= Win7. | |
| 132 size_t flags_size = sizeof(flags); | |
| 133 | |
| 134 EXPECT_TRUE(startup_info.InitializeProcThreadAttributeList(1)); | |
| 135 EXPECT_TRUE(startup_info.UpdateProcThreadAttribute( | |
| 136 PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &flags, flags_size)); | |
| 137 creation_flags = EXTENDED_STARTUPINFO_PRESENT; | |
| 138 } | |
| 139 | |
| 140 std::wstring cmd_line = L"sbox_integration_test_win_proc.exe "; | |
| 141 scoped_ptr<wchar_t, base::FreeDeleter> cmd_writeable( | |
| 142 ::wcsdup(cmd_line.c_str())); | |
| 143 | |
| 144 EXPECT_TRUE(::CreateProcessW(NULL, cmd_writeable.get(), NULL, NULL, FALSE, | |
| 145 creation_flags, NULL, NULL, | |
| 146 startup_info.startup_info(), pi)); | |
| 147 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(*event, event_max_wait_ms)); | |
| 148 | |
| 149 return; | |
| 150 } | |
| 151 | |
| 152 //------------------------------------------------------------------------------ | |
| 153 // 1. Spawn our Windows process (with or without mitigation enabled). | |
| 154 // 2. Load our hook Dll locally. | |
| 155 // 3. Start the hook (for our WinProc or globally). | |
| 156 // 4. Send a keystroke event. | |
| 157 // 5. Ask the hook Dll if it received a hook callback. | |
| 158 // 6. Cleanup the hooking. | |
| 159 // 7. Signal our Windows process to shutdown. | |
| 160 // | |
| 161 // Do NOT use any ASSERTs in this function. Cleanup required. | |
| 162 //------------------------------------------------------------------------------ | |
| 163 | |
| 164 typedef BOOL (*WasHookCalledFunction)(); | |
| 165 | |
| 166 void TestWin8ExtensionPointHookWrapper(bool is_success_test, bool global_hook) { | |
| 167 HMODULE dll = NULL; | |
|
Will Harris
2016/04/04 00:15:09
chromium style is to declare variables just before
penny
2016/04/11 22:11:58
Done.
| |
| 168 HHOOK hook = NULL; | |
| 169 HOOKPROC hook_proc = NULL; | |
| 170 WasHookCalledFunction WasHookCalled = NULL; | |
| 171 PROCESS_INFORMATION proc_info = {}; | |
| 172 | |
| 173 // 1. Spawn WinProc. | |
| 174 HANDLE event = ::CreateEventW(NULL, FALSE, FALSE, winproc_event); | |
| 175 EXPECT_TRUE(event != NULL && event != INVALID_HANDLE_VALUE); | |
| 176 SpawnWinProc(&proc_info, is_success_test, &event); | |
| 177 | |
| 178 // 2. Load the hook DLL. | |
| 179 dll = ::LoadLibraryW(L"sbox_integration_test_hook_dll.dll"); | |
|
Will Harris
2016/04/04 00:15:08
prefer ScopedNativeLibrary here rather than LoadLi
penny
2016/04/11 22:11:58
Done.
| |
| 180 EXPECT_TRUE(dll); | |
| 181 | |
| 182 hook_proc = reinterpret_cast<HOOKPROC>(::GetProcAddress(dll, "HookProc")); | |
| 183 WasHookCalled = reinterpret_cast<WasHookCalledFunction>( | |
| 184 ::GetProcAddress(dll, "WasHookCalled")); | |
|
Will Harris
2016/04/04 00:15:08
you could #define WasHookCalled in a .h file for y
penny
2016/04/11 22:11:59
Acknowledged. I've created a new common.h file wi
| |
| 185 EXPECT_TRUE(hook_proc && WasHookCalled); | |
| 186 | |
| 187 // 3. Try installing the hook (either on our remote target thread, | |
| 188 // or globally). | |
| 189 DWORD target = 0; | |
| 190 if (!global_hook) | |
| 191 target = proc_info.dwThreadId; | |
| 192 hook = ::SetWindowsHookExW(WH_KEYBOARD, hook_proc, dll, target); | |
| 193 EXPECT_TRUE(hook); | |
| 194 | |
| 195 // 4. Inject a keyboard event. | |
| 196 | |
| 197 // Note: that PostThreadMessage and SendMessage APIs will not deliver | |
| 198 // a keystroke in such a way that triggers a "legitimate" hook. | |
| 199 // Have to use targetless SendInput or keybd_event. The latter is | |
| 200 // less code and easier to work with. | |
| 201 keybd_event(VkKeyScan(L'A'), 0, 0, 0); | |
| 202 std::this_thread::sleep_for(std::chrono::milliseconds(500)); | |
|
Will Harris
2016/04/04 00:15:09
base::PlatformThread::Sleep() and base::TimeDelta
penny
2016/04/11 22:11:58
Done.
| |
| 203 keybd_event(VkKeyScan(L'A'), 0, KEYEVENTF_KEYUP, 0); | |
| 204 | |
| 205 // Give it a chance... | |
| 206 std::this_thread::sleep_for(std::chrono::seconds(1)); | |
| 207 | |
| 208 // 5. Did our hook get hit? Did we expect it to? | |
| 209 if (global_hook) | |
| 210 EXPECT_EQ((is_success_test ? TRUE : FALSE), WasHookCalled()); | |
|
Will Harris
2016/04/04 00:15:08
true and false not TRUE and FALSE
penny
2016/04/11 22:11:59
Done.
The function WasHookCalled() was actually d
| |
| 211 else | |
| 212 // ***IMPORTANT: when targeting a specific thread id, the | |
| 213 // PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE | |
| 214 // mitigation does NOT disable the hook API. It ONLY | |
| 215 // stops global hooks from running in your process. Hence, | |
| 216 // we expect the hook to have hit (TRUE) even in the "failure" | |
| 217 // case for a non-global/targetted hook. | |
| 218 EXPECT_EQ((is_success_test ? TRUE : TRUE), WasHookCalled()); | |
| 219 | |
| 220 // 6. Rip it all down. | |
| 221 if (hook) | |
| 222 EXPECT_TRUE(::UnhookWindowsHookEx(hook)); | |
| 223 if (dll) | |
| 224 EXPECT_TRUE(::FreeLibrary(dll)); | |
|
Will Harris
2016/04/04 00:15:08
this can go if you are using ScopedNativeLibrary
penny
2016/04/11 22:11:59
Done.
| |
| 225 | |
| 226 // 7. Trigger shutdown of WinProc. | |
| 227 if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { | |
| 228 // Note: The combination/perfect-storm of a Global Hook, in a | |
| 229 // WinProc that has the EXTENSION_POINT_DISABLE mitigation ON, and the | |
| 230 // use of the SendInput or keybd_event API to inject a keystroke, | |
| 231 // results in the target becoming unresponsive. If any one of these states | |
| 232 // are changed, the problem does not occur. | |
| 233 // This means the WM_QUIT message is not handled and the call to | |
| 234 // WaitForSingleObject times out. Therefore not checking the return val. | |
| 235 ::WaitForSingleObject(event, event_max_wait_ms); | |
| 236 EXPECT_TRUE(::CloseHandle(event)); | |
| 237 } else { | |
| 238 // Make sure we don't leave a stray. | |
| 239 ::TerminateProcess(proc_info.hProcess, 0); | |
| 240 EXPECT_TRUE(false); | |
| 241 } | |
| 242 EXPECT_TRUE(::CloseHandle(proc_info.hThread)); | |
| 243 EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); | |
| 244 } | |
| 245 | |
| 246 //------------------------------------------------------------------------------ | |
| 247 // 1. Set up our AppInit Dll in registry settings. (Enable) | |
| 248 // 2. Spawn our Windows process (with or without mitigation enabled). | |
| 249 // 3. Check if our AppInit Dll is loaded in our Windows process or not. | |
| 250 // 4. Signal our Windows process to shutdown. | |
| 251 // 5. Restore original reg settings. | |
| 252 // | |
| 253 // Do NOT use any ASSERTs in this function. Cleanup required. | |
| 254 //------------------------------------------------------------------------------ | |
| 255 void TestWin8ExtensionPointAppInitWrapper(bool is_success_test) { | |
| 256 PROCESS_INFORMATION proc_info = {}; | |
| 257 wchar_t* hook_dll = L"sbox_integration_test_hook_dll.dll"; | |
|
Will Harris
2016/04/04 00:15:08
const
penny
2016/04/11 22:11:58
Done.
| |
| 258 | |
| 259 // Get path of current executable. | |
| 260 wchar_t path[MAX_PATH]; | |
|
Will Harris
2016/04/04 00:15:08
not sure exactly what is happening here, you are g
penny
2016/04/11 22:11:59
I actually don't think FilePath helps at all. I'v
Will Harris
2016/04/12 19:39:12
I understand you need to call GetShortPathName as
penny
2016/04/13 22:52:27
Done.
I'm not really convinced this is much nicer
| |
| 261 EXPECT_TRUE(::GetModuleFileNameW(NULL, path, MAX_PATH)); | |
| 262 // We just want the directory. | |
| 263 wchar_t* last_separator = ::wcsrchr(path, L'\\'); | |
| 264 EXPECT_TRUE(last_separator); | |
| 265 last_separator++; | |
| 266 *last_separator = L'\0'; | |
| 267 ::wcsncat(path, hook_dll, (MAX_PATH - ::wcslen(path))); | |
| 268 // Prep short-name path to our hook dll, for registry. | |
| 269 DWORD length = ::GetShortPathNameW(path, NULL, 0); | |
| 270 wchar_t* short_name = new wchar_t[length]; | |
|
Will Harris
2016/04/04 00:15:08
use a scoped_ptr with a base::FreeDeleter rather t
penny
2016/04/11 22:11:59
Done.
| |
| 271 EXPECT_TRUE(::GetShortPathNameW(path, short_name, length)); | |
| 272 | |
| 273 // 1. Reg setup. | |
| 274 wchar_t* app_init_reg_path = | |
| 275 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"; | |
| 276 wchar_t* dlls_value_name = L"AppInit_DLLs"; | |
| 277 wchar_t* enabled_value_name = L"LoadAppInit_DLLs"; | |
| 278 wchar_t* signing_value_name = L"RequireSignedAppInit_DLLs"; | |
| 279 std::wstring orig_dlls; | |
| 280 std::wstring new_dlls; | |
| 281 DWORD orig_enabled_value = 0; | |
| 282 DWORD orig_signing_value = 0; | |
| 283 base::win::RegKey app_init_key(HKEY_LOCAL_MACHINE, app_init_reg_path, | |
| 284 KEY_QUERY_VALUE | KEY_SET_VALUE); | |
| 285 // Backup the existing settings. | |
| 286 EXPECT_TRUE(app_init_key.Valid()); | |
| 287 EXPECT_TRUE(app_init_key.HasValue(dlls_value_name) && | |
| 288 app_init_key.HasValue(enabled_value_name)); | |
| 289 EXPECT_EQ(ERROR_SUCCESS, app_init_key.ReadValue(dlls_value_name, &orig_dlls)); | |
| 290 EXPECT_EQ(ERROR_SUCCESS, | |
| 291 app_init_key.ReadValueDW(enabled_value_name, &orig_enabled_value)); | |
| 292 if (app_init_key.HasValue(signing_value_name)) | |
| 293 EXPECT_EQ(ERROR_SUCCESS, app_init_key.ReadValueDW(signing_value_name, | |
| 294 &orig_signing_value)); | |
| 295 | |
| 296 // Set the new settings we want (obviously requires local admin privileges). | |
| 297 new_dlls = orig_dlls; | |
| 298 if (0 != orig_dlls.compare(L"")) | |
| 299 new_dlls.append(L","); | |
| 300 new_dlls.append(short_name); | |
| 301 delete[] short_name; | |
| 302 | |
| 303 EXPECT_EQ(ERROR_SUCCESS, | |
| 304 app_init_key.WriteValue(dlls_value_name, new_dlls.c_str())); | |
| 305 if (app_init_key.HasValue(signing_value_name)) | |
| 306 EXPECT_EQ(ERROR_SUCCESS, app_init_key.WriteValue(signing_value_name, | |
| 307 static_cast<DWORD>(0))); | |
| 308 EXPECT_EQ(ERROR_SUCCESS, | |
| 309 app_init_key.WriteValue(enabled_value_name, static_cast<DWORD>(1))); | |
|
Will Harris
2016/04/04 00:15:09
can you just use 1U and avoid the cast here and ab
penny
2016/04/11 22:11:59
So the EXPECT_EQ macro (and the function call) is
| |
| 310 | |
| 311 // 2. Spawn WinProc. | |
| 312 HANDLE event = ::CreateEventW(NULL, FALSE, FALSE, winproc_event); | |
|
Will Harris
2016/04/04 00:15:09
ScopedHandle
penny
2016/04/11 22:11:58
Done.
| |
| 313 EXPECT_TRUE(event != NULL && event != INVALID_HANDLE_VALUE); | |
| 314 SpawnWinProc(&proc_info, is_success_test, &event); | |
| 315 | |
| 316 // 3. Check loaded modules in WinProc to see if AppInit dll is loaded. | |
| 317 std::vector<HMODULE>(modules); | |
| 318 EXPECT_TRUE( | |
| 319 base::win::GetLoadedModulesSnapshot(proc_info.hProcess, &modules)); | |
| 320 BOOL dll_loaded = FALSE; | |
| 321 | |
| 322 for (auto module : modules) { | |
| 323 wchar_t name[MAX_PATH]; | |
| 324 EXPECT_TRUE( | |
| 325 ::GetModuleFileNameExW(proc_info.hProcess, module, name, MAX_PATH)); | |
| 326 | |
| 327 // Compare to our dll name! | |
| 328 if (::wcsstr(name, hook_dll)) { | |
| 329 // Found it. | |
| 330 dll_loaded = TRUE; | |
| 331 break; | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 // Did we pass the test as expected? | |
| 336 EXPECT_EQ((is_success_test ? TRUE : FALSE), dll_loaded); | |
| 337 | |
| 338 // 4. Trigger shutdown of WinProc. | |
| 339 if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { | |
| 340 ::WaitForSingleObject(event, event_max_wait_ms); | |
| 341 EXPECT_TRUE(::CloseHandle(event)); | |
| 342 } else { | |
| 343 // Make sure we don't leave a stray. | |
| 344 ::TerminateProcess(proc_info.hProcess, 0); | |
| 345 EXPECT_TRUE(false); | |
| 346 } | |
| 347 EXPECT_TRUE(::CloseHandle(proc_info.hThread)); | |
| 348 EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); | |
| 349 | |
| 350 // 5. Reg Restore | |
| 351 EXPECT_EQ(ERROR_SUCCESS, | |
| 352 app_init_key.WriteValue(enabled_value_name, orig_enabled_value)); | |
| 353 if (app_init_key.HasValue(signing_value_name)) | |
| 354 EXPECT_EQ(ERROR_SUCCESS, | |
| 355 app_init_key.WriteValue(signing_value_name, orig_signing_value)); | |
| 356 EXPECT_EQ(ERROR_SUCCESS, | |
| 357 app_init_key.WriteValue(dlls_value_name, orig_dlls.c_str())); | |
| 358 app_init_key.Close(); | |
| 359 } | |
| 360 | |
| 109 void TestWin10ImageLoadRemote(bool is_success_test) { | 361 void TestWin10ImageLoadRemote(bool is_success_test) { |
| 110 // ***Insert your manual testing share UNC path here! | 362 // ***Insert your manual testing share UNC path here! |
| 111 // E.g.: \\\\hostname\\sharename\\calc.exe | 363 // E.g.: \\\\hostname\\sharename\\calc.exe |
| 112 std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\""; | 364 std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\""; |
| 113 | 365 |
| 114 sandbox::TestRunner runner; | 366 sandbox::TestRunner runner; |
| 115 sandbox::TargetPolicy* policy = runner.GetPolicy(); | 367 sandbox::TargetPolicy* policy = runner.GetPolicy(); |
| 116 | 368 |
| 117 // Set a policy that would normally allow for process creation. | 369 // Set a policy that would normally allow for process creation. |
| 118 policy->SetJobLevel(sandbox::JOB_NONE, 0); | 370 policy->SetJobLevel(sandbox::JOB_NONE, 0); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 setup_proc.Terminate(desired_exit_code, false); | 481 setup_proc.Terminate(desired_exit_code, false); |
| 230 return SBOX_TEST_SUCCEEDED; | 482 return SBOX_TEST_SUCCEEDED; |
| 231 } | 483 } |
| 232 // Note: GetLastError from CreateProcess returns 5, "ERROR_ACCESS_DENIED". | 484 // Note: GetLastError from CreateProcess returns 5, "ERROR_ACCESS_DENIED". |
| 233 return SBOX_TEST_FAILED; | 485 return SBOX_TEST_FAILED; |
| 234 } | 486 } |
| 235 | 487 |
| 236 //------------------------------------------------------------------------------ | 488 //------------------------------------------------------------------------------ |
| 237 // Win8 Checks: | 489 // Win8 Checks: |
| 238 // MITIGATION_DEP(_NO_ATL_THUNK) | 490 // MITIGATION_DEP(_NO_ATL_THUNK) |
| 239 // MITIGATION_EXTENSION_DLL_DISABLE | |
| 240 // MITIGATION_RELOCATE_IMAGE(_REQUIRED) - ASLR, release only | 491 // MITIGATION_RELOCATE_IMAGE(_REQUIRED) - ASLR, release only |
| 241 // MITIGATION_STRICT_HANDLE_CHECKS | 492 // MITIGATION_STRICT_HANDLE_CHECKS |
| 242 // >= Win8 | 493 // >= Win8 |
| 243 //------------------------------------------------------------------------------ | 494 //------------------------------------------------------------------------------ |
| 244 | 495 |
| 245 SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { | 496 SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t **argv) { |
| 246 get_process_mitigation_policy = | 497 get_process_mitigation_policy = |
| 247 reinterpret_cast<GetProcessMitigationPolicyFunction>( | 498 reinterpret_cast<GetProcessMitigationPolicyFunction>( |
| 248 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), | 499 ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), |
| 249 "GetProcessMitigationPolicy")); | 500 "GetProcessMitigationPolicy")); |
| 250 if (!get_process_mitigation_policy) | 501 if (!get_process_mitigation_policy) |
| 251 return SBOX_TEST_NOT_FOUND; | 502 return SBOX_TEST_NOT_FOUND; |
| 252 | 503 |
| 253 #if !defined(_WIN64) // DEP is always enabled on 64-bit. | 504 #if !defined(_WIN64) // DEP is always enabled on 64-bit. |
| 254 if (!CheckWin8DepPolicy()) | 505 if (!CheckWin8DepPolicy()) |
| 255 return SBOX_TEST_FIRST_ERROR; | 506 return SBOX_TEST_FIRST_ERROR; |
| 256 #endif | 507 #endif |
| 257 | 508 |
| 258 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. | 509 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. |
| 259 if (!CheckWin8AslrPolicy()) | 510 if (!CheckWin8AslrPolicy()) |
| 260 return SBOX_TEST_SECOND_ERROR; | 511 return SBOX_TEST_SECOND_ERROR; |
| 261 #endif | 512 #endif |
| 262 | 513 |
| 263 if (!CheckWin8StrictHandlePolicy()) | 514 if (!CheckWin8StrictHandlePolicy()) |
| 264 return SBOX_TEST_THIRD_ERROR; | 515 return SBOX_TEST_THIRD_ERROR; |
| 265 | 516 |
| 266 if (!CheckWin8DllExtensionPolicy()) | |
| 267 return SBOX_TEST_FIFTH_ERROR; | |
| 268 | |
| 269 return SBOX_TEST_SUCCEEDED; | 517 return SBOX_TEST_SUCCEEDED; |
| 270 } | 518 } |
| 271 | 519 |
| 272 TEST(ProcessMitigationsTest, CheckWin8) { | 520 TEST(ProcessMitigationsTest, CheckWin8) { |
| 273 if (base::win::GetVersion() < base::win::VERSION_WIN8) | 521 if (base::win::GetVersion() < base::win::VERSION_WIN8) |
| 274 return; | 522 return; |
| 275 | 523 |
| 276 TestRunner runner; | 524 TestRunner runner; |
| 277 sandbox::TargetPolicy* policy = runner.GetPolicy(); | 525 sandbox::TargetPolicy* policy = runner.GetPolicy(); |
| 278 | 526 |
| 279 sandbox::MitigationFlags mitigations = MITIGATION_DEP | | 527 sandbox::MitigationFlags mitigations = |
| 280 MITIGATION_DEP_NO_ATL_THUNK | | 528 MITIGATION_DEP | MITIGATION_DEP_NO_ATL_THUNK; |
| 281 MITIGATION_EXTENSION_DLL_DISABLE; | |
| 282 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. | 529 #if defined(NDEBUG) // ASLR cannot be forced in debug builds. |
| 283 mitigations |= MITIGATION_RELOCATE_IMAGE | | 530 mitigations |= MITIGATION_RELOCATE_IMAGE | |
| 284 MITIGATION_RELOCATE_IMAGE_REQUIRED; | 531 MITIGATION_RELOCATE_IMAGE_REQUIRED; |
| 285 #endif | 532 #endif |
| 286 | 533 |
| 287 EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); | 534 EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); |
| 288 | 535 |
| 289 mitigations |= MITIGATION_STRICT_HANDLE_CHECKS; | 536 mitigations |= MITIGATION_STRICT_HANDLE_CHECKS; |
| 290 | 537 |
| 291 EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); | 538 EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 | 653 |
| 407 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), | 654 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), |
| 408 SBOX_ALL_OK); | 655 SBOX_ALL_OK); |
| 409 EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, | 656 EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, |
| 410 sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL), | 657 sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL), |
| 411 sandbox::SBOX_ALL_OK); | 658 sandbox::SBOX_ALL_OK); |
| 412 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); | 659 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); |
| 413 } | 660 } |
| 414 | 661 |
| 415 //------------------------------------------------------------------------------ | 662 //------------------------------------------------------------------------------ |
| 663 // Disable extension points (MITIGATION_EXTENSION_POINT_DISABLE). | |
| 664 // >= Win8 | |
| 665 //------------------------------------------------------------------------------ | |
| 666 | |
| 667 wchar_t* extension_point_mutex = L"ChromeExtensionTestMutex"; | |
| 668 DWORD mutex_max_wait_ms = 10 * 1000; | |
|
Will Harris
2016/04/04 00:15:08
TestTimeouts::action_timeout() for defaults
penny
2016/04/11 22:11:58
So TestTimeouts::action_timeout() returns a base::
| |
| 669 | |
| 670 SBOX_TESTS_COMMAND int CheckWin8ExtensionPointSetting(int argc, | |
| 671 wchar_t** argv) { | |
| 672 get_process_mitigation_policy = | |
| 673 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( | |
| 674 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); | |
| 675 if (!get_process_mitigation_policy) | |
| 676 return SBOX_TEST_NOT_FOUND; | |
| 677 | |
| 678 if (!CheckWin8ExtensionPointPolicy()) | |
| 679 return SBOX_TEST_FIRST_ERROR; | |
| 680 return SBOX_TEST_SUCCEEDED; | |
| 681 } | |
| 682 | |
| 683 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE | |
| 684 // mitigation enables the setting on a process. | |
| 685 TEST(ProcessMitigationsTest, CheckWin8ExtensionPointPolicySuccess) { | |
| 686 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
| 687 return; | |
| 688 | |
| 689 TestRunner runner; | |
| 690 sandbox::TargetPolicy* policy = runner.GetPolicy(); | |
| 691 | |
| 692 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_EXTENSION_POINT_DISABLE), | |
| 693 SBOX_ALL_OK); | |
| 694 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | |
| 695 runner.RunTest(L"CheckWin8ExtensionPointSetting")); | |
| 696 } | |
| 697 | |
| 698 // This test validates that we CAN add a "legitimate" global hook on the | |
| 699 // sandboxed | |
| 700 // proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. | |
| 701 // | |
| 702 // MANUAL testing only. | |
| 703 TEST(ProcessMitigationsTest, | |
| 704 DISABLED_CheckWin8ExtensionPoint_GlobalHook_Success) { | |
| 705 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
| 706 return; | |
| 707 | |
| 708 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); | |
| 709 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); | |
| 710 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); | |
| 711 | |
| 712 // (is_success_test, global_hook) | |
| 713 TestWin8ExtensionPointHookWrapper(true, true); | |
| 714 | |
| 715 EXPECT_TRUE(::ReleaseMutex(mutex)); | |
| 716 EXPECT_TRUE(::CloseHandle(mutex)); | |
| 717 } | |
| 718 | |
| 719 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE | |
| 720 // mitigation prevents a global hook in our WinProc. | |
| 721 // | |
| 722 // MANUAL testing only. | |
| 723 TEST(ProcessMitigationsTest, | |
| 724 DISABLED_CheckWin8ExtensionPoint_GlobalHook_Failure) { | |
| 725 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
| 726 return; | |
| 727 | |
| 728 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); | |
| 729 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); | |
| 730 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); | |
| 731 | |
| 732 // (is_success_test, global_hook) | |
| 733 TestWin8ExtensionPointHookWrapper(false, true); | |
| 734 | |
| 735 EXPECT_TRUE(::ReleaseMutex(mutex)); | |
| 736 EXPECT_TRUE(::CloseHandle(mutex)); | |
| 737 } | |
| 738 | |
| 739 // This test validates that we CAN add a "legitimate" hook on the sandboxed | |
| 740 // proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. | |
| 741 // | |
| 742 // MANUAL testing only. | |
| 743 TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Success) { | |
| 744 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
| 745 return; | |
| 746 | |
| 747 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); | |
| 748 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); | |
| 749 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); | |
| 750 | |
| 751 // (is_success_test, global_hook) | |
| 752 TestWin8ExtensionPointHookWrapper(true, false); | |
| 753 | |
| 754 EXPECT_TRUE(::ReleaseMutex(mutex)); | |
| 755 EXPECT_TRUE(::CloseHandle(mutex)); | |
| 756 } | |
| 757 | |
| 758 // *** Important: MITIGATION_EXTENSION_POINT_DISABLE does NOT prevent | |
| 759 // hooks targetted at a specific thread id. It only prevents | |
| 760 // global hooks. So this test does NOT actually expect the hook | |
| 761 // to fail (see TestWin8ExtensionPointHookWrapper function) even | |
| 762 // with the mitigation on. | |
| 763 // | |
| 764 // MANUAL testing only. | |
| 765 TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Failure) { | |
| 766 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
| 767 return; | |
| 768 | |
| 769 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); | |
| 770 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); | |
| 771 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); | |
| 772 | |
| 773 // (is_success_test, global_hook) | |
| 774 TestWin8ExtensionPointHookWrapper(false, false); | |
| 775 | |
| 776 EXPECT_TRUE(::ReleaseMutex(mutex)); | |
| 777 EXPECT_TRUE(::CloseHandle(mutex)); | |
| 778 } | |
| 779 | |
| 780 // This test validates that we CAN add an AppInit Dll to a target | |
| 781 // WinProc if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. | |
| 782 // | |
| 783 // MANUAL testing only. | |
| 784 // Must run this test as admin/elevated. | |
| 785 TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Success) { | |
| 786 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
| 787 return; | |
| 788 | |
| 789 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); | |
| 790 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); | |
| 791 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); | |
| 792 | |
| 793 TestWin8ExtensionPointAppInitWrapper(true); | |
| 794 | |
| 795 EXPECT_TRUE(::ReleaseMutex(mutex)); | |
| 796 EXPECT_TRUE(::CloseHandle(mutex)); | |
| 797 } | |
| 798 | |
| 799 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE | |
| 800 // mitigation prevents the loading of any AppInit Dll into our WinProc. | |
| 801 // | |
| 802 // MANUAL testing only. | |
| 803 // Must run this test as admin/elevated. | |
| 804 TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Failure) { | |
| 805 if (base::win::GetVersion() < base::win::VERSION_WIN8) | |
| 806 return; | |
| 807 | |
| 808 HANDLE mutex = ::CreateMutexW(NULL, FALSE, extension_point_mutex); | |
| 809 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); | |
| 810 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, mutex_max_wait_ms)); | |
| 811 | |
| 812 TestWin8ExtensionPointAppInitWrapper(false); | |
| 813 | |
| 814 EXPECT_TRUE(::ReleaseMutex(mutex)); | |
| 815 EXPECT_TRUE(::CloseHandle(mutex)); | |
| 816 } | |
| 817 | |
| 818 //------------------------------------------------------------------------------ | |
| 416 // Disable non-system font loads (MITIGATION_NONSYSTEM_FONT_DISABLE) | 819 // Disable non-system font loads (MITIGATION_NONSYSTEM_FONT_DISABLE) |
| 417 // >= Win10 | 820 // >= Win10 |
| 418 //------------------------------------------------------------------------------ | 821 //------------------------------------------------------------------------------ |
| 419 | 822 |
| 420 SBOX_TESTS_COMMAND int CheckWin10FontLockDown(int argc, wchar_t** argv) { | 823 SBOX_TESTS_COMMAND int CheckWin10FontLockDown(int argc, wchar_t** argv) { |
| 421 get_process_mitigation_policy = | 824 get_process_mitigation_policy = |
| 422 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( | 825 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
| 423 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); | 826 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
| 424 if (!get_process_mitigation_policy) | 827 if (!get_process_mitigation_policy) |
| 425 return SBOX_TEST_NOT_FOUND; | 828 return SBOX_TEST_NOT_FOUND; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 policy->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE), | 973 policy->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE), |
| 571 SBOX_ALL_OK); | 974 SBOX_ALL_OK); |
| 572 EXPECT_EQ(SBOX_TEST_SUCCEEDED, | 975 EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
| 573 runner.RunTest(L"CheckWin10ImageLoadNoRemote")); | 976 runner.RunTest(L"CheckWin10ImageLoadNoRemote")); |
| 574 } | 977 } |
| 575 | 978 |
| 576 // This test validates that we CAN create a new process from | 979 // This test validates that we CAN create a new process from |
| 577 // a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE | 980 // a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE |
| 578 // mitigation is NOT set. | 981 // mitigation is NOT set. |
| 579 // | 982 // |
| 580 // DISABLED for automated testing bots. Enable for manual testing. | 983 // MANUAL testing only. |
| 581 TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) { | 984 TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) { |
| 582 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) | 985 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
| 583 return; | 986 return; |
| 584 | 987 |
| 585 TestWin10ImageLoadRemote(true); | 988 TestWin10ImageLoadRemote(true); |
| 586 } | 989 } |
| 587 | 990 |
| 588 // This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE | 991 // This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE |
| 589 // mitigation prevents creating a new process from a remote | 992 // mitigation prevents creating a new process from a remote |
| 590 // UNC device. | 993 // UNC device. |
| 591 // | 994 // |
| 592 // DISABLED for automated testing bots. Enable for manual testing. | 995 // MANUAL testing only. |
| 593 TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) { | 996 TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) { |
| 594 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) | 997 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
| 595 return; | 998 return; |
| 596 | 999 |
| 597 TestWin10ImageLoadRemote(false); | 1000 TestWin10ImageLoadRemote(false); |
| 598 } | 1001 } |
| 599 | 1002 |
| 600 //------------------------------------------------------------------------------ | 1003 //------------------------------------------------------------------------------ |
| 601 // Disable image load when "mandatory low label" (integrity level). | 1004 // Disable image load when "mandatory low label" (integrity level). |
| 602 // (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL) | 1005 // (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL) |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 cmd = cmd.Append(L"calc.exe"); | 1152 cmd = cmd.Append(L"calc.exe"); |
| 750 | 1153 |
| 751 std::wstring test_command = L"TestChildProcess "; | 1154 std::wstring test_command = L"TestChildProcess "; |
| 752 test_command += cmd.value().c_str(); | 1155 test_command += cmd.value().c_str(); |
| 753 test_command += L" 1"; | 1156 test_command += L" 1"; |
| 754 | 1157 |
| 755 EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(test_command.c_str())); | 1158 EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(test_command.c_str())); |
| 756 } | 1159 } |
| 757 | 1160 |
| 758 } // namespace sandbox | 1161 } // namespace sandbox |
| OLD | NEW |