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

Side by Side Diff: sandbox/win/src/process_mitigations_test.cc

Issue 2944493002: [Windows Sandbox Tests] Process Mitigations. (Closed)
Patch Set: Code review fixes, part 2. Created 3 years, 5 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 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 "sandbox/win/src/process_mitigations.h"
6
7 #include <d3d9.h>
8 #include <initguid.h>
9 #include <opmapi.h>
10 #include <psapi.h>
11 #include <windows.h>
12
13 #include <map>
14 #include <string>
15
16 #include "base/command_line.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_temp_dir.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/path_service.h"
21 #include "base/process/launch.h"
22 #include "base/scoped_native_library.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/test/test_timeouts.h"
26 #include "base/win/registry.h"
27 #include "base/win/scoped_handle.h"
28 #include "base/win/startup_information.h"
29 #include "base/win/win_util.h"
30 #include "base/win/windows_version.h"
31 #include "sandbox/win/src/nt_internals.h"
32 #include "sandbox/win/src/process_mitigations_win32k_policy.h"
33 #include "sandbox/win/src/sandbox.h"
34 #include "sandbox/win/src/sandbox_factory.h"
35 #include "sandbox/win/src/target_services.h"
36 #include "sandbox/win/tests/common/controller.h"
37 #include "sandbox/win/tests/integration_tests/integration_tests_common.h"
38 #include "testing/gtest/include/gtest/gtest.h"
39
40 namespace {
41
42 // Timeouts for synchronization.
43 #define event_timeout \
44 static_cast<DWORD>((TestTimeouts::action_timeout()).InMillisecondsRoundedUp())
45
46 // API defined in winbase.h.
47 typedef decltype(GetProcessDEPPolicy)* GetProcessDEPPolicyFunction;
48
49 // API defined in processthreadsapi.h.
50 typedef decltype(
51 GetProcessMitigationPolicy)* GetProcessMitigationPolicyFunction;
52 GetProcessMitigationPolicyFunction get_process_mitigation_policy;
53
54 // APIs defined in wingdi.h.
55 typedef decltype(AddFontMemResourceEx)* AddFontMemResourceExFunction;
56 typedef decltype(RemoveFontMemResourceEx)* RemoveFontMemResourceExFunction;
57
58 // APIs defined in integration_tests_common.h
59 typedef decltype(WasHookCalled)* WasHookCalledFunction;
60 typedef decltype(SetHook)* SetHookFunction;
61
62 #if !defined(_WIN64)
63 bool CheckWin8DepPolicy() {
64 PROCESS_MITIGATION_DEP_POLICY policy = {};
65 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy,
66 &policy, sizeof(policy))) {
67 return false;
68 }
69 return policy.Enable && policy.Permanent;
70 }
71 #endif // !defined(_WIN64)
72
73 bool CheckWin8AslrPolicy() {
74 PROCESS_MITIGATION_ASLR_POLICY policy = {};
75 if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy,
76 &policy, sizeof(policy))) {
77 return false;
78 }
79 return policy.EnableForceRelocateImages && policy.DisallowStrippedImages;
80 }
81
82 bool CheckWin8StrictHandlePolicy() {
83 PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy = {};
84 if (!get_process_mitigation_policy(::GetCurrentProcess(),
85 ProcessStrictHandleCheckPolicy, &policy,
86 sizeof(policy))) {
87 return false;
88 }
89 return policy.RaiseExceptionOnInvalidHandleReference &&
90 policy.HandleExceptionsPermanentlyEnabled;
91 }
92
93 bool CheckWin8Win32CallPolicy() {
94 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {};
95 if (!get_process_mitigation_policy(::GetCurrentProcess(),
96 ProcessSystemCallDisablePolicy, &policy,
97 sizeof(policy))) {
98 return false;
99 }
100 return policy.DisallowWin32kSystemCalls;
101 }
102
103 bool CheckWin8ExtensionPointPolicy() {
104 PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {};
105 if (!get_process_mitigation_policy(::GetCurrentProcess(),
106 ProcessExtensionPointDisablePolicy,
107 &policy, sizeof(policy))) {
108 return false;
109 }
110 return policy.DisableExtensionPoints;
111 }
112
113 bool CheckWin10FontPolicy() {
114 PROCESS_MITIGATION_FONT_DISABLE_POLICY policy = {};
115 if (!get_process_mitigation_policy(::GetCurrentProcess(),
116 ProcessFontDisablePolicy, &policy,
117 sizeof(policy))) {
118 return false;
119 }
120 return policy.DisableNonSystemFonts;
121 }
122
123 bool CheckWin10ImageLoadNoRemotePolicy() {
124 PROCESS_MITIGATION_IMAGE_LOAD_POLICY policy = {};
125 if (!get_process_mitigation_policy(::GetCurrentProcess(),
126 ProcessImageLoadPolicy, &policy,
127 sizeof(policy))) {
128 return false;
129 }
130 return policy.NoRemoteImages;
131 }
132
133 // Spawn Windows process (with or without mitigation enabled).
134 bool SpawnWinProc(PROCESS_INFORMATION* pi, bool success_test, HANDLE* event) {
135 base::win::StartupInformation startup_info;
136 DWORD creation_flags = 0;
137
138 if (!success_test) {
139 DWORD64 flags =
140 PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON;
141 // This test only runs on >= Win8, so don't have to handle
142 // illegal 64-bit flags on 32-bit <= Win7.
143 size_t flags_size = sizeof(flags);
144
145 if (!startup_info.InitializeProcThreadAttributeList(1) ||
146 !startup_info.UpdateProcThreadAttribute(
147 PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &flags, flags_size)) {
148 ADD_FAILURE();
149 return false;
150 }
151 creation_flags = EXTENDED_STARTUPINFO_PRESENT;
152 }
153
154 // Command line must be writable.
155 base::string16 cmd_writeable(g_winproc_file);
156
157 if (!::CreateProcessW(NULL, &cmd_writeable[0], NULL, NULL, FALSE,
158 creation_flags, NULL, NULL, startup_info.startup_info(),
159 pi)) {
160 ADD_FAILURE();
161 return false;
162 }
163 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(*event, event_timeout));
164
165 return true;
166 }
167
168 //------------------------------------------------------------------------------
169 // 1. Spawn a Windows process (with or without mitigation enabled).
170 // 2. Load the hook Dll locally.
171 // 3. Create a global named event for the hook to trigger.
172 // 4. Start the hook (for the specific WinProc or globally).
173 // 5. Send a keystroke event.
174 // 6. Ask the hook Dll if it received a hook callback.
175 // 7. Cleanup the hooking.
176 // 8. Signal the Windows process to shutdown.
177 //
178 // Do NOT use any ASSERTs in this function. Cleanup required.
179 //------------------------------------------------------------------------------
180 void TestWin8ExtensionPointHookWrapper(bool is_success_test, bool global_hook) {
181 // Set up a couple global events that this test will use.
182 HANDLE winproc_event = ::CreateEventW(NULL, FALSE, FALSE, g_winproc_event);
183 if (winproc_event == NULL || winproc_event == INVALID_HANDLE_VALUE) {
184 ADD_FAILURE();
185 return;
186 }
187 base::win::ScopedHandle scoped_winproc_event(winproc_event);
188
189 HANDLE hook_event = ::CreateEventW(NULL, FALSE, FALSE, g_hook_event);
190 if (hook_event == NULL || hook_event == INVALID_HANDLE_VALUE) {
191 ADD_FAILURE();
192 return;
193 }
194 base::win::ScopedHandle scoped_hook_event(hook_event);
195
196 // 1. Spawn WinProc.
197 PROCESS_INFORMATION proc_info = {};
198 if (!SpawnWinProc(&proc_info, is_success_test, &winproc_event))
199 return;
200
201 // From this point on, no return on failure. Cleanup required.
202 bool all_good = true;
203
204 // 2. Load the hook DLL.
205 base::FilePath hook_dll_path(g_hook_dll_file);
206 base::ScopedNativeLibrary dll(hook_dll_path);
207 EXPECT_TRUE(dll.is_valid());
208
209 HOOKPROC hook_proc =
210 reinterpret_cast<HOOKPROC>(dll.GetFunctionPointer(g_hook_handler_func));
211 WasHookCalledFunction was_hook_called =
212 reinterpret_cast<WasHookCalledFunction>(
213 dll.GetFunctionPointer(g_was_hook_called_func));
214 SetHookFunction set_hook = reinterpret_cast<SetHookFunction>(
215 dll.GetFunctionPointer(g_set_hook_func));
216 if (!hook_proc || !was_hook_called || !set_hook) {
217 ADD_FAILURE();
218 all_good = false;
219 }
220
221 // 3. Try installing the hook (either on a remote target thread,
222 // or globally).
223 HHOOK hook = nullptr;
224 if (all_good) {
225 DWORD target = 0;
226 if (!global_hook)
227 target = proc_info.dwThreadId;
228 hook = ::SetWindowsHookExW(WH_KEYBOARD, hook_proc, dll.get(), target);
229 if (!hook) {
230 ADD_FAILURE();
231 all_good = false;
232 } else
233 // Pass the hook DLL the hook handle.
234 set_hook(hook);
235 }
236
237 // 4. Inject a keyboard event.
238 if (all_good) {
239 // Note: that PostThreadMessage and SendMessage APIs will not deliver
240 // a keystroke in such a way that triggers a "legitimate" hook.
241 // Have to use targetless SendInput or keybd_event. The latter is
242 // less code and easier to work with.
243 keybd_event(VkKeyScan(L'A'), 0, 0, 0);
244 keybd_event(VkKeyScan(L'A'), 0, KEYEVENTF_KEYUP, 0);
245 // Give it a chance to hit the hook handler...
246 ::WaitForSingleObject(hook_event, event_timeout);
247
248 // 5. Did the hook get hit? Was it expected to?
249 if (global_hook)
250 EXPECT_EQ((is_success_test ? true : false), was_hook_called());
251 else
252 // ***IMPORTANT: when targeting a specific thread id, the
253 // PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE
254 // mitigation does NOT disable the hook API. It ONLY
255 // stops global hooks from running in a process. Hence,
256 // the hook will hit (TRUE) even in the "failure"
257 // case for a non-global/targeted hook.
258 EXPECT_EQ((is_success_test ? true : true), was_hook_called());
259 }
260
261 // 6. Disable hook.
262 if (hook)
263 EXPECT_TRUE(::UnhookWindowsHookEx(hook));
264
265 // 7. Trigger shutdown of WinProc.
266 if (proc_info.hProcess) {
267 if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) {
268 // Note: The combination/perfect-storm of a Global Hook, in a
269 // WinProc that has the EXTENSION_POINT_DISABLE mitigation ON, and the
270 // use of the SendInput or keybd_event API to inject a keystroke,
271 // results in the target becoming unresponsive. If any one of these
272 // states are changed, the problem does not occur. This means the WM_QUIT
273 // message is not handled and the call to WaitForSingleObject times out.
274 // Therefore not checking the return val.
275 ::WaitForSingleObject(winproc_event, event_timeout);
276 } else {
277 // Ensure no strays.
278 ::TerminateProcess(proc_info.hProcess, 0);
279 ADD_FAILURE();
280 }
281 EXPECT_TRUE(::CloseHandle(proc_info.hThread));
282 EXPECT_TRUE(::CloseHandle(proc_info.hProcess));
283 }
284 }
285
286 //------------------------------------------------------------------------------
287 // 1. Set up the AppInit Dll in registry settings. (Enable)
288 // 2. Spawn a Windows process (with or without mitigation enabled).
289 // 3. Check if the AppInit Dll got loaded in the Windows process or not.
290 // 4. Signal the Windows process to shutdown.
291 // 5. Restore original reg settings.
292 //
293 // Do NOT use any ASSERTs in this function. Cleanup required.
294 //------------------------------------------------------------------------------
295 void TestWin8ExtensionPointAppInitWrapper(bool is_success_test) {
296 // 0.5 Get path of current module. The appropriate build of the
297 // AppInit DLL will be in the same directory (and the
298 // full path is needed for reg).
299 wchar_t path[MAX_PATH];
300 if (!::GetModuleFileNameW(NULL, path, MAX_PATH)) {
301 ADD_FAILURE();
302 return;
303 }
304 // Only want the directory. Switch file name for the AppInit DLL.
305 base::FilePath full_dll_path(path);
306 full_dll_path = full_dll_path.DirName();
307 full_dll_path = full_dll_path.Append(g_hook_dll_file);
308 wchar_t* non_const = const_cast<wchar_t*>(full_dll_path.value().c_str());
309 // Now make sure the path is in "short-name" form for registry.
310 DWORD length = ::GetShortPathNameW(non_const, NULL, 0);
311 std::vector<wchar_t> short_name(length);
312 if (!::GetShortPathNameW(non_const, &short_name[0], length)) {
313 ADD_FAILURE();
314 return;
315 }
316
317 // 1. Reg setup.
318 const wchar_t* app_init_reg_path =
319 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
320 const wchar_t* dlls_value_name = L"AppInit_DLLs";
321 const wchar_t* enabled_value_name = L"LoadAppInit_DLLs";
322 const wchar_t* signing_value_name = L"RequireSignedAppInit_DLLs";
323 std::wstring orig_dlls;
324 std::wstring new_dlls;
325 DWORD orig_enabled_value = 0;
326 DWORD orig_signing_value = 0;
327 base::win::RegKey app_init_key(HKEY_LOCAL_MACHINE, app_init_reg_path,
328 KEY_QUERY_VALUE | KEY_SET_VALUE);
329 // Backup the existing settings.
330 if (!app_init_key.Valid() || !app_init_key.HasValue(dlls_value_name) ||
331 !app_init_key.HasValue(enabled_value_name) ||
332 ERROR_SUCCESS != app_init_key.ReadValue(dlls_value_name, &orig_dlls) ||
333 ERROR_SUCCESS !=
334 app_init_key.ReadValueDW(enabled_value_name, &orig_enabled_value)) {
335 ADD_FAILURE();
336 return;
337 }
338 if (app_init_key.HasValue(signing_value_name)) {
339 if (ERROR_SUCCESS !=
340 app_init_key.ReadValueDW(signing_value_name, &orig_signing_value)) {
341 ADD_FAILURE();
342 return;
343 }
344 }
345
346 // Set the new settings (obviously requires local admin privileges).
347 new_dlls = orig_dlls;
348 if (!orig_dlls.empty())
349 new_dlls.append(L",");
350 new_dlls.append(short_name.data());
351
352 // From this point on, no return on failure. Cleanup required.
353 bool all_good = true;
354
355 if (app_init_key.HasValue(signing_value_name)) {
356 if (ERROR_SUCCESS !=
357 app_init_key.WriteValue(signing_value_name, static_cast<DWORD>(0))) {
358 ADD_FAILURE();
359 all_good = false;
360 }
361 }
362 if (ERROR_SUCCESS !=
363 app_init_key.WriteValue(dlls_value_name, new_dlls.c_str()) ||
364 ERROR_SUCCESS !=
365 app_init_key.WriteValue(enabled_value_name, static_cast<DWORD>(1))) {
366 ADD_FAILURE();
367 all_good = false;
368 }
369
370 // 2. Spawn WinProc.
371 HANDLE winproc_event = INVALID_HANDLE_VALUE;
372 base::win::ScopedHandle scoped_event;
373 PROCESS_INFORMATION proc_info = {};
374 if (all_good) {
375 winproc_event = ::CreateEventW(NULL, FALSE, FALSE, g_winproc_event);
376 if (winproc_event == NULL || winproc_event == INVALID_HANDLE_VALUE) {
377 ADD_FAILURE();
378 all_good = false;
379 } else {
380 scoped_event.Set(winproc_event);
381 if (!SpawnWinProc(&proc_info, is_success_test, &winproc_event))
382 all_good = false;
383 }
384 }
385
386 // 3. Check loaded modules in WinProc to see if the AppInit dll is loaded.
387 bool dll_loaded = false;
388 if (all_good) {
389 std::vector<HMODULE>(modules);
390 if (!base::win::GetLoadedModulesSnapshot(proc_info.hProcess, &modules)) {
391 ADD_FAILURE();
392 all_good = false;
393 } else {
394 for (HMODULE module : modules) {
395 wchar_t name[MAX_PATH] = {};
396 if (::GetModuleFileNameExW(proc_info.hProcess, module, name,
397 MAX_PATH) &&
398 ::wcsstr(name, g_hook_dll_file)) {
399 // Found it.
400 dll_loaded = true;
401 break;
402 }
403 }
404 }
405 }
406
407 // Was the test result as expected?
408 if (all_good)
409 EXPECT_EQ((is_success_test ? true : false), dll_loaded);
410
411 // 4. Trigger shutdown of WinProc.
412 if (proc_info.hProcess) {
413 if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) {
414 ::WaitForSingleObject(winproc_event, event_timeout);
415 } else {
416 // Ensure no strays.
417 ::TerminateProcess(proc_info.hProcess, 0);
418 ADD_FAILURE();
419 }
420 EXPECT_TRUE(::CloseHandle(proc_info.hThread));
421 EXPECT_TRUE(::CloseHandle(proc_info.hProcess));
422 }
423
424 // 5. Reg Restore
425 EXPECT_EQ(ERROR_SUCCESS,
426 app_init_key.WriteValue(enabled_value_name, orig_enabled_value));
427 if (app_init_key.HasValue(signing_value_name))
428 EXPECT_EQ(ERROR_SUCCESS,
429 app_init_key.WriteValue(signing_value_name, orig_signing_value));
430 EXPECT_EQ(ERROR_SUCCESS,
431 app_init_key.WriteValue(dlls_value_name, orig_dlls.c_str()));
432 }
433
434 void TestWin10ImageLoadRemote(bool is_success_test) {
435 // ***Insert a manual testing share UNC path here!
436 // E.g.: \\\\hostname\\sharename\\calc.exe
437 std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\"";
438
439 sandbox::TestRunner runner;
440 sandbox::TargetPolicy* policy = runner.GetPolicy();
441
442 // Set a policy that would normally allow for process creation.
443 policy->SetJobLevel(sandbox::JOB_NONE, 0);
444 policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED);
445 runner.SetDisableCsrss(false);
446
447 if (!is_success_test) {
448 // Enable the NoRemote mitigation.
449 EXPECT_EQ(policy->SetDelayedProcessMitigations(
450 sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE),
451 sandbox::SBOX_ALL_OK);
452 }
453
454 std::wstring test = L"TestChildProcess ";
455 test += unc.c_str();
456 EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED
457 : sandbox::SBOX_TEST_FAILED),
458 runner.RunTest(test.c_str()));
459 }
460
461 bool CheckWin10ImageLoadNoLowLabelPolicy() {
462 PROCESS_MITIGATION_IMAGE_LOAD_POLICY policy = {};
463 if (!get_process_mitigation_policy(::GetCurrentProcess(),
464 ProcessImageLoadPolicy, &policy,
465 sizeof(policy))) {
466 return false;
467 }
468 return policy.NoLowMandatoryLabelImages;
469 }
470
471 void TestWin10ImageLoadLowLabel(bool is_success_test) {
472 // Setup a mandatory low executable for this test (calc.exe).
473 // If anything fails during setup, ASSERT to end test.
474 base::FilePath orig_path;
475 ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &orig_path));
476 orig_path = orig_path.Append(L"calc.exe");
477
478 base::ScopedTempDir temp_dir;
479 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
480 base::FilePath new_path = temp_dir.GetPath();
481 new_path = new_path.Append(L"lowIL_calc.exe");
482
483 // Test file will be cleaned up by the ScopedTempDir.
484 ASSERT_TRUE(base::CopyFileW(orig_path, new_path));
485
486 std::wstring cmd_line = L"icacls \"";
487 cmd_line += new_path.value().c_str();
488 cmd_line += L"\" /setintegritylevel Low";
489
490 base::LaunchOptions options = base::LaunchOptionsForTest();
491 base::Process setup_proc = base::LaunchProcess(cmd_line.c_str(), options);
492 ASSERT_TRUE(setup_proc.IsValid());
493
494 int exit_code = 1;
495 if (!setup_proc.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(10),
496 &exit_code)) {
497 // Might have timed out, or might have failed.
498 // Terminate to make sure we clean up any mess.
499 setup_proc.Terminate(0, false);
500 ASSERT_TRUE(false);
501 }
502 // Make sure icacls was successful.
503 ASSERT_EQ(0, exit_code);
504
505 sandbox::TestRunner runner;
506 sandbox::TargetPolicy* policy = runner.GetPolicy();
507
508 // Set a policy that would normally allow for process creation.
509 policy->SetJobLevel(sandbox::JOB_NONE, 0);
510 policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED);
511 runner.SetDisableCsrss(false);
512
513 if (!is_success_test) {
514 // Enable the NoLowLabel mitigation.
515 EXPECT_EQ(policy->SetDelayedProcessMitigations(
516 sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
517 sandbox::SBOX_ALL_OK);
518 }
519
520 std::wstring test = L"TestChildProcess ";
521 test += new_path.value().c_str();
522
523 EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED
524 : sandbox::SBOX_TEST_FAILED),
525 runner.RunTest(test.c_str()));
526 }
527
528 BOOL CALLBACK MonitorEnumCallback(HMONITOR monitor,
529 HDC hdc_monitor,
530 LPRECT rect_monitor,
531 LPARAM data) {
532 std::map<HMONITOR, base::string16>& monitors =
533 *reinterpret_cast<std::map<HMONITOR, base::string16>*>(data);
534 MONITORINFOEXW monitor_info = {};
535 monitor_info.cbSize = sizeof(monitor_info);
536
537 if (!::GetMonitorInfoW(monitor,
538 reinterpret_cast<MONITORINFO*>(&monitor_info)))
539 return FALSE;
540 monitors[monitor] = monitor_info.szDevice;
541 return TRUE;
542 }
543
544 std::map<HMONITOR, std::wstring> EnumerateMonitors() {
545 std::map<HMONITOR, std::wstring> result;
546 ::EnumDisplayMonitors(nullptr, nullptr, MonitorEnumCallback,
547 reinterpret_cast<LPARAM>(&result));
548 return result;
549 }
550
551 #define HMONITOR_ENTRY(monitor) \
552 result[reinterpret_cast<HMONITOR>(monitor)] = \
553 base::StringPrintf(L"\\\\.\\DISPLAY%X", monitor)
554
555 std::map<HMONITOR, std::wstring> GetTestMonitors() {
556 std::map<HMONITOR, std::wstring> result;
557
558 HMONITOR_ENTRY(0x11111111);
559 HMONITOR_ENTRY(0x22222222);
560 HMONITOR_ENTRY(0x44444444);
561 HMONITOR_ENTRY(0x88888888);
562 return result;
563 }
564
565 std::wstring UnicodeStringToString(PUNICODE_STRING name) {
566 return std::wstring(name->Buffer,
567 name->Buffer + (name->Length / sizeof(name->Buffer[0])));
568 }
569
570 // Returns an index 1, 2, 4 or 8 depening on the device. 0 on error.
571 DWORD GetTestDeviceMonitorIndex(PUNICODE_STRING device_name) {
572 std::wstring name = UnicodeStringToString(device_name);
573 std::map<HMONITOR, std::wstring> monitors = GetTestMonitors();
574 for (const auto& monitor : monitors) {
575 if (name == monitor.second)
576 return static_cast<DWORD>(reinterpret_cast<uintptr_t>(monitor.first)) &
577 0xF;
578 }
579 return 0;
580 }
581
582 NTSTATUS WINAPI GetSuggestedOPMProtectedOutputArraySizeTest(
583 PUNICODE_STRING device_name,
584 DWORD* suggested_output_array_size) {
585 DWORD monitor = GetTestDeviceMonitorIndex(device_name);
586 if (!monitor)
587 return STATUS_OBJECT_NAME_NOT_FOUND;
588 *suggested_output_array_size = monitor;
589 return STATUS_SUCCESS;
590 }
591
592 NTSTATUS WINAPI
593 CreateOPMProtectedOutputsTest(PUNICODE_STRING device_name,
594 DXGKMDT_OPM_VIDEO_OUTPUT_SEMANTICS vos,
595 DWORD output_array_size,
596 DWORD* num_in_output_array,
597 OPM_PROTECTED_OUTPUT_HANDLE* output_array) {
598 DWORD monitor = GetTestDeviceMonitorIndex(device_name);
599 if (!monitor)
600 return STATUS_OBJECT_NAME_NOT_FOUND;
601 if (vos != DXGKMDT_OPM_VOS_OPM_SEMANTICS)
602 return STATUS_INVALID_PARAMETER;
603 if (output_array_size != monitor)
604 return STATUS_INVALID_PARAMETER;
605 *num_in_output_array = monitor - 1;
606 for (DWORD index = 0; index < monitor - 1; ++index) {
607 output_array[index] =
608 reinterpret_cast<OPM_PROTECTED_OUTPUT_HANDLE>((monitor << 4) + index);
609 }
610 return STATUS_SUCCESS;
611 }
612
613 ULONG CalculateCertLength(ULONG monitor) {
614 return (monitor * 0x800) + 0xabc;
615 }
616
617 NTSTATUS WINAPI GetCertificateTest(PUNICODE_STRING device_name,
618 DXGKMDT_CERTIFICATE_TYPE certificate_type,
619 BYTE* certificate,
620 ULONG certificate_length) {
621 DWORD monitor = GetTestDeviceMonitorIndex(device_name);
622 if (!monitor)
623 return STATUS_OBJECT_NAME_NOT_FOUND;
624 if (certificate_type != DXGKMDT_OPM_CERTIFICATE)
625 return STATUS_INVALID_PARAMETER;
626 if (certificate_length != CalculateCertLength(monitor))
627 return STATUS_INVALID_PARAMETER;
628 memset(certificate, 'A' + monitor, certificate_length);
629 return STATUS_SUCCESS;
630 }
631
632 NTSTATUS WINAPI
633 GetCertificateSizeTest(PUNICODE_STRING device_name,
634 DXGKMDT_CERTIFICATE_TYPE certificate_type,
635 ULONG* certificate_length) {
636 DWORD monitor = GetTestDeviceMonitorIndex(device_name);
637 if (!monitor)
638 return STATUS_OBJECT_NAME_NOT_FOUND;
639 if (certificate_type != DXGKMDT_OPM_CERTIFICATE)
640 return STATUS_INVALID_PARAMETER;
641 *certificate_length = CalculateCertLength(monitor);
642 return STATUS_SUCCESS;
643 }
644
645 // Check for valid output handle and return the monitor index.
646 DWORD IsValidProtectedOutput(OPM_PROTECTED_OUTPUT_HANDLE protected_output) {
647 uintptr_t handle = reinterpret_cast<uintptr_t>(protected_output);
648 uintptr_t monitor = handle >> 4;
649 uintptr_t index = handle & 0xF;
650 switch (monitor) {
651 case 1:
652 case 2:
653 case 4:
654 case 8:
655 break;
656 default:
657 return 0;
658 }
659 if (index >= (monitor - 1))
660 return 0;
661 return static_cast<DWORD>(monitor);
662 }
663
664 NTSTATUS WINAPI
665 GetCertificateByHandleTest(OPM_PROTECTED_OUTPUT_HANDLE protected_output,
666 DXGKMDT_CERTIFICATE_TYPE certificate_type,
667 BYTE* certificate,
668 ULONG certificate_length) {
669 DWORD monitor = IsValidProtectedOutput(protected_output);
670 if (!monitor)
671 return STATUS_INVALID_HANDLE;
672 if (certificate_type != DXGKMDT_OPM_CERTIFICATE)
673 return STATUS_INVALID_PARAMETER;
674 if (certificate_length != CalculateCertLength(monitor))
675 return STATUS_INVALID_PARAMETER;
676 memset(certificate, 'A' + monitor, certificate_length);
677 return STATUS_SUCCESS;
678 }
679
680 NTSTATUS WINAPI
681 GetCertificateSizeByHandleTest(OPM_PROTECTED_OUTPUT_HANDLE protected_output,
682 DXGKMDT_CERTIFICATE_TYPE certificate_type,
683 ULONG* certificate_length) {
684 DWORD monitor = IsValidProtectedOutput(protected_output);
685 if (!monitor)
686 return STATUS_INVALID_HANDLE;
687 if (certificate_type != DXGKMDT_OPM_CERTIFICATE)
688 return STATUS_INVALID_PARAMETER;
689 *certificate_length = CalculateCertLength(monitor);
690 return STATUS_SUCCESS;
691 }
692
693 NTSTATUS WINAPI
694 DestroyOPMProtectedOutputTest(OPM_PROTECTED_OUTPUT_HANDLE protected_output) {
695 if (!IsValidProtectedOutput(protected_output))
696 return STATUS_INVALID_HANDLE;
697 return STATUS_SUCCESS;
698 }
699
700 NTSTATUS WINAPI ConfigureOPMProtectedOutputTest(
701 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
702 const DXGKMDT_OPM_CONFIGURE_PARAMETERS* parameters,
703 ULONG additional_parameters_size,
704 const BYTE* additional_parameters) {
705 if (!IsValidProtectedOutput(protected_output))
706 return STATUS_INVALID_HANDLE;
707 if (additional_parameters && additional_parameters_size)
708 return STATUS_INVALID_PARAMETER;
709 return STATUS_SUCCESS;
710 }
711
712 NTSTATUS WINAPI GetOPMInformationTest(
713 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
714 const DXGKMDT_OPM_GET_INFO_PARAMETERS* parameters,
715 DXGKMDT_OPM_REQUESTED_INFORMATION* requested_information) {
716 DWORD monitor = IsValidProtectedOutput(protected_output);
717 if (!monitor)
718 return STATUS_INVALID_HANDLE;
719 memset(requested_information, '0' + monitor,
720 sizeof(DXGKMDT_OPM_REQUESTED_INFORMATION));
721 return STATUS_SUCCESS;
722 }
723
724 NTSTATUS WINAPI
725 GetOPMRandomNumberTest(OPM_PROTECTED_OUTPUT_HANDLE protected_output,
726 DXGKMDT_OPM_RANDOM_NUMBER* random_number) {
727 DWORD monitor = IsValidProtectedOutput(protected_output);
728 if (!monitor)
729 return STATUS_INVALID_HANDLE;
730 memset(random_number->abRandomNumber, '!' + monitor,
731 sizeof(random_number->abRandomNumber));
732 return STATUS_SUCCESS;
733 }
734
735 NTSTATUS WINAPI SetOPMSigningKeyAndSequenceNumbersTest(
736 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
737 const DXGKMDT_OPM_ENCRYPTED_PARAMETERS* parameters) {
738 DWORD monitor = IsValidProtectedOutput(protected_output);
739 if (!monitor)
740 return STATUS_INVALID_HANDLE;
741 DXGKMDT_OPM_ENCRYPTED_PARAMETERS test_params = {};
742 memset(test_params.abEncryptedParameters, 'a' + monitor,
743 sizeof(test_params.abEncryptedParameters));
744 if (memcmp(test_params.abEncryptedParameters,
745 parameters->abEncryptedParameters,
746 sizeof(test_params.abEncryptedParameters)) != 0)
747 return STATUS_INVALID_PARAMETER;
748 return STATUS_SUCCESS;
749 }
750
751 BOOL WINAPI EnumDisplayMonitorsTest(HDC hdc,
752 LPCRECT clip_rect,
753 MONITORENUMPROC enum_function,
754 LPARAM data) {
755 RECT rc = {};
756 for (const auto& monitor : GetTestMonitors()) {
757 if (!enum_function(monitor.first, hdc, &rc, data))
758 return FALSE;
759 }
760 return TRUE;
761 }
762
763 BOOL WINAPI GetMonitorInfoWTest(HMONITOR monitor, LPMONITORINFO monitor_info) {
764 std::map<HMONITOR, std::wstring> monitors = GetTestMonitors();
765 if (monitor_info->cbSize != sizeof(MONITORINFO) &&
766 monitor_info->cbSize != sizeof(MONITORINFOEXW))
767 return FALSE;
768 auto it = monitors.find(monitor);
769 if (it == monitors.end())
770 return FALSE;
771 if (monitor_info->cbSize == sizeof(MONITORINFOEXW)) {
772 MONITORINFOEXW* monitor_info_ex =
773 reinterpret_cast<MONITORINFOEXW*>(monitor_info);
774 size_t copy_size = (it->second.size() + 1) * sizeof(WCHAR);
775 if (copy_size > sizeof(monitor_info_ex->szDevice) - sizeof(WCHAR))
776 copy_size = sizeof(monitor_info_ex->szDevice) - sizeof(WCHAR);
777 memset(monitor_info_ex->szDevice, 0, sizeof(monitor_info_ex->szDevice));
778 memcpy(monitor_info_ex->szDevice, it->second.c_str(), copy_size);
779 }
780 return TRUE;
781 }
782
783 #define RETURN_TEST_FUNC(n) \
784 if (strcmp(name, #n) == 0) { \
785 return n##Test; \
786 }
787
788 void* FunctionOverrideForTest(const char* name) {
789 RETURN_TEST_FUNC(GetSuggestedOPMProtectedOutputArraySize);
790 RETURN_TEST_FUNC(CreateOPMProtectedOutputs);
791 RETURN_TEST_FUNC(GetCertificate);
792 RETURN_TEST_FUNC(GetCertificateSize);
793 RETURN_TEST_FUNC(DestroyOPMProtectedOutput);
794 RETURN_TEST_FUNC(ConfigureOPMProtectedOutput);
795 RETURN_TEST_FUNC(GetOPMInformation);
796 RETURN_TEST_FUNC(GetOPMRandomNumber);
797 RETURN_TEST_FUNC(SetOPMSigningKeyAndSequenceNumbers);
798 RETURN_TEST_FUNC(EnumDisplayMonitors);
799 RETURN_TEST_FUNC(GetMonitorInfoW);
800 RETURN_TEST_FUNC(GetCertificateByHandle);
801 RETURN_TEST_FUNC(GetCertificateSizeByHandle);
802 NOTREACHED();
803 return nullptr;
804 }
805
806 } // namespace
807
808 namespace sandbox {
809
810 // A shared helper test command that will attempt to CreateProcess with a given
811 // command line. The second optional parameter will cause the child process to
812 // return that as an exit code on termination.
813 //
814 // ***Make sure you've enabled basic process creation in the
815 // test sandbox settings via:
816 // sandbox::TargetPolicy::SetJobLevel(),
817 // sandbox::TargetPolicy::SetTokenLevel(),
818 // and TestRunner::SetDisableCsrss().
819 SBOX_TESTS_COMMAND int TestChildProcess(int argc, wchar_t** argv) {
820 if (argc < 1)
821 return SBOX_TEST_INVALID_PARAMETER;
822
823 int desired_exit_code = 0;
824
825 if (argc == 2) {
826 desired_exit_code = wcstoul(argv[1], nullptr, 0);
827 }
828
829 std::wstring cmd = argv[0];
830 base::LaunchOptions options = base::LaunchOptionsForTest();
831 base::Process setup_proc = base::LaunchProcess(cmd.c_str(), options);
832
833 if (setup_proc.IsValid()) {
834 setup_proc.Terminate(desired_exit_code, false);
835 return SBOX_TEST_SUCCEEDED;
836 }
837 // Note: GetLastError from CreateProcess returns 5, "ERROR_ACCESS_DENIED".
838 return SBOX_TEST_FAILED;
839 }
840
841 //------------------------------------------------------------------------------
842 // Win8 Checks:
843 // MITIGATION_DEP(_NO_ATL_THUNK)
844 // MITIGATION_RELOCATE_IMAGE(_REQUIRED) - ASLR
845 // MITIGATION_STRICT_HANDLE_CHECKS
846 // >= Win8
847 //------------------------------------------------------------------------------
848
849 SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t** argv) {
850 get_process_mitigation_policy =
851 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress(
852 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy"));
853 if (!get_process_mitigation_policy)
854 return SBOX_TEST_NOT_FOUND;
855
856 #if !defined(_WIN64) // DEP is always enabled on 64-bit.
857 if (!CheckWin8DepPolicy())
858 return SBOX_TEST_FIRST_ERROR;
859 #endif
860
861 if (!CheckWin8AslrPolicy())
862 return SBOX_TEST_SECOND_ERROR;
863
864 if (!CheckWin8StrictHandlePolicy())
865 return SBOX_TEST_THIRD_ERROR;
866
867 return SBOX_TEST_SUCCEEDED;
868 }
869
870 TEST(ProcessMitigationsTest, CheckWin8) {
871 if (base::win::GetVersion() < base::win::VERSION_WIN8)
872 return;
873
874 TestRunner runner;
875 sandbox::TargetPolicy* policy = runner.GetPolicy();
876
877 // ASLR cannot be forced on start in debug builds.
878 constexpr sandbox::MitigationFlags kDebugDelayedMitigations =
879 MITIGATION_RELOCATE_IMAGE | MITIGATION_RELOCATE_IMAGE_REQUIRED;
880
881 sandbox::MitigationFlags mitigations =
882 MITIGATION_DEP | MITIGATION_DEP_NO_ATL_THUNK;
883 #if defined(NDEBUG)
884 mitigations |= kDebugDelayedMitigations;
885 #endif
886
887 EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK);
888
889 mitigations |= MITIGATION_STRICT_HANDLE_CHECKS;
890
891 #if !defined(NDEBUG)
892 mitigations |= kDebugDelayedMitigations;
893 #endif
894
895 EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK);
896
897 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8"));
898 }
899
900 //------------------------------------------------------------------------------
901 // DEP (MITIGATION_DEP)
902 // < Win8 x86
903 //------------------------------------------------------------------------------
904
905 SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t** argv) {
906 GetProcessDEPPolicyFunction get_process_dep_policy =
907 reinterpret_cast<GetProcessDEPPolicyFunction>(::GetProcAddress(
908 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy"));
909 if (get_process_dep_policy) {
910 BOOL is_permanent = FALSE;
911 DWORD dep_flags = 0;
912
913 if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags,
914 &is_permanent)) {
915 return SBOX_TEST_FIRST_ERROR;
916 }
917
918 if (!(dep_flags & PROCESS_DEP_ENABLE) || !is_permanent)
919 return SBOX_TEST_SECOND_ERROR;
920
921 } else {
922 NtQueryInformationProcessFunction query_information_process = NULL;
923 ResolveNTFunctionPtr("NtQueryInformationProcess",
924 &query_information_process);
925 if (!query_information_process)
926 return SBOX_TEST_NOT_FOUND;
927
928 ULONG size = 0;
929 ULONG dep_flags = 0;
930 if (!SUCCEEDED(query_information_process(::GetCurrentProcess(),
931 ProcessExecuteFlags, &dep_flags,
932 sizeof(dep_flags), &size))) {
933 return SBOX_TEST_THIRD_ERROR;
934 }
935
936 static const int MEM_EXECUTE_OPTION_DISABLE = 2;
937 static const int MEM_EXECUTE_OPTION_PERMANENT = 8;
938 dep_flags &= 0xff;
939
940 if (dep_flags !=
941 (MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_PERMANENT)) {
942 return SBOX_TEST_FOURTH_ERROR;
943 }
944 }
945
946 return SBOX_TEST_SUCCEEDED;
947 }
948
949 #if !defined(_WIN64) // DEP is always enabled on 64-bit.
950 TEST(ProcessMitigationsTest, CheckDep) {
951 if (base::win::GetVersion() >= base::win::VERSION_WIN8)
952 return;
953
954 TestRunner runner;
955 sandbox::TargetPolicy* policy = runner.GetPolicy();
956
957 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_DEP |
958 MITIGATION_DEP_NO_ATL_THUNK |
959 MITIGATION_SEHOP),
960 SBOX_ALL_OK);
961 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep"));
962 }
963 #endif
964
965 //------------------------------------------------------------------------------
966 // Win32k Lockdown (MITIGATION_WIN32K_DISABLE)
967 // >= Win8
968 //------------------------------------------------------------------------------
969
970 SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t** argv) {
971 get_process_mitigation_policy =
972 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress(
973 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy"));
974 if (!get_process_mitigation_policy)
975 return SBOX_TEST_NOT_FOUND;
976
977 if (!CheckWin8Win32CallPolicy())
978 return SBOX_TEST_FIRST_ERROR;
979 return SBOX_TEST_SUCCEEDED;
980 }
981
982 SBOX_TESTS_COMMAND int CheckWin8MonitorsRedirection(int argc, wchar_t** argv) {
983 std::map<HMONITOR, base::string16> monitors = EnumerateMonitors();
984 std::map<HMONITOR, base::string16> monitors_to_test = GetTestMonitors();
985 if (monitors.size() != monitors_to_test.size())
986 return SBOX_TEST_FIRST_ERROR;
987
988 for (const auto& monitor : monitors) {
989 auto result = monitors_to_test.find(monitor.first);
990 if (result == monitors_to_test.end())
991 return SBOX_TEST_SECOND_ERROR;
992 if (result->second != monitor.second)
993 return SBOX_TEST_THIRD_ERROR;
994 }
995 return SBOX_TEST_SUCCEEDED;
996 }
997
998 SBOX_TESTS_COMMAND int CheckWin8MonitorInfo(int argc, wchar_t** argv) {
999 std::map<HMONITOR, base::string16> monitors_to_test = GetTestMonitors();
1000 MONITORINFO monitor_info = {};
1001 MONITORINFOEXW monitor_info_exw = {};
1002 MONITORINFOEXA monitor_info_exa = {};
1003 HMONITOR valid_monitor = monitors_to_test.begin()->first;
1004 std::wstring valid_device = monitors_to_test.begin()->second;
1005 monitor_info.cbSize = sizeof(MONITORINFO);
1006 if (!::GetMonitorInfoW(valid_monitor, &monitor_info))
1007 return SBOX_TEST_FIRST_ERROR;
1008 monitor_info.cbSize = sizeof(MONITORINFO);
1009 if (!::GetMonitorInfoA(valid_monitor, &monitor_info))
1010 return SBOX_TEST_SECOND_ERROR;
1011 monitor_info_exw.cbSize = sizeof(MONITORINFOEXW);
1012 if (!::GetMonitorInfoW(valid_monitor,
1013 reinterpret_cast<MONITORINFO*>(&monitor_info_exw)) ||
1014 valid_device != monitor_info_exw.szDevice) {
1015 return SBOX_TEST_THIRD_ERROR;
1016 }
1017 monitor_info_exa.cbSize = sizeof(MONITORINFOEXA);
1018 if (!::GetMonitorInfoA(valid_monitor,
1019 reinterpret_cast<MONITORINFO*>(&monitor_info_exa)) ||
1020 valid_device != base::ASCIIToUTF16(monitor_info_exa.szDevice)) {
1021 return SBOX_TEST_FOURTH_ERROR;
1022 }
1023
1024 // Invalid size checks.
1025 monitor_info.cbSize = 0;
1026 if (::GetMonitorInfoW(valid_monitor, &monitor_info))
1027 return SBOX_TEST_FIFTH_ERROR;
1028 monitor_info.cbSize = 0x10000;
1029 if (::GetMonitorInfoW(valid_monitor, &monitor_info))
1030 return SBOX_TEST_SIXTH_ERROR;
1031
1032 // Check that an invalid handle isn't accepted.
1033 HMONITOR invalid_monitor = reinterpret_cast<HMONITOR>(-1);
1034 monitor_info.cbSize = sizeof(MONITORINFO);
1035 if (::GetMonitorInfoW(invalid_monitor, &monitor_info))
1036 return SBOX_TEST_SEVENTH_ERROR;
1037
1038 return SBOX_TEST_SUCCEEDED;
1039 }
1040
1041 bool RunTestsOnVideoOutputConfigure(uintptr_t monitor_index,
1042 IOPMVideoOutput* video_output) {
1043 OPM_CONFIGURE_PARAMETERS config_params = {};
1044 OPM_SET_PROTECTION_LEVEL_PARAMETERS* protection_level =
1045 reinterpret_cast<OPM_SET_PROTECTION_LEVEL_PARAMETERS*>(
1046 config_params.abParameters);
1047 protection_level->ulProtectionType = OPM_PROTECTION_TYPE_HDCP;
1048 protection_level->ulProtectionLevel = OPM_HDCP_ON;
1049 config_params.guidSetting = OPM_SET_PROTECTION_LEVEL;
1050 config_params.cbParametersSize = sizeof(OPM_SET_PROTECTION_LEVEL_PARAMETERS);
1051 HRESULT hr = video_output->Configure(&config_params, 0, nullptr);
1052 if (FAILED(hr))
1053 return false;
1054 protection_level->ulProtectionType = OPM_PROTECTION_TYPE_DPCP;
1055 hr = video_output->Configure(&config_params, 0, nullptr);
1056 if (FAILED(hr))
1057 return false;
1058 protection_level->ulProtectionLevel = OPM_HDCP_OFF;
1059 hr = video_output->Configure(&config_params, 0, nullptr);
1060 if (FAILED(hr))
1061 return false;
1062 BYTE dummy_byte = 0;
1063 hr = video_output->Configure(&config_params, 1, &dummy_byte);
1064 if (SUCCEEDED(hr))
1065 return false;
1066 protection_level->ulProtectionType = 0xFFFFFFFF;
1067 hr = video_output->Configure(&config_params, 0, nullptr);
1068 if (SUCCEEDED(hr))
1069 return false;
1070 // Invalid protection level test.
1071 protection_level->ulProtectionType = OPM_PROTECTION_TYPE_HDCP;
1072 protection_level->ulProtectionLevel = OPM_HDCP_ON + 1;
1073 hr = video_output->Configure(&config_params, 0, nullptr);
1074 if (SUCCEEDED(hr))
1075 return false;
1076 hr = video_output->Configure(&config_params, 0, nullptr);
1077 if (SUCCEEDED(hr))
1078 return false;
1079 config_params.guidSetting = OPM_SET_HDCP_SRM;
1080 OPM_SET_HDCP_SRM_PARAMETERS* srm_parameters =
1081 reinterpret_cast<OPM_SET_HDCP_SRM_PARAMETERS*>(
1082 config_params.abParameters);
1083 srm_parameters->ulSRMVersion = 1;
1084 config_params.cbParametersSize = sizeof(OPM_SET_HDCP_SRM_PARAMETERS);
1085 hr = video_output->Configure(&config_params, 0, nullptr);
1086 if (SUCCEEDED(hr))
1087 return false;
1088 return true;
1089 }
1090
1091 bool RunTestsOnVideoOutputFinishInitialization(uintptr_t monitor_index,
1092 IOPMVideoOutput* video_output) {
1093 OPM_ENCRYPTED_INITIALIZATION_PARAMETERS init_params = {};
1094 memset(init_params.abEncryptedInitializationParameters, 'a' + monitor_index,
1095 sizeof(init_params.abEncryptedInitializationParameters));
1096 HRESULT hr = video_output->FinishInitialization(&init_params);
1097 if (FAILED(hr))
1098 return false;
1099 memset(init_params.abEncryptedInitializationParameters, 'Z' + monitor_index,
1100 sizeof(init_params.abEncryptedInitializationParameters));
1101 hr = video_output->FinishInitialization(&init_params);
1102 if (SUCCEEDED(hr))
1103 return false;
1104 return true;
1105 }
1106
1107 bool RunTestsOnVideoOutputStartInitialization(uintptr_t monitor_index,
1108 IOPMVideoOutput* video_output) {
1109 OPM_RANDOM_NUMBER random_number = {};
1110 BYTE* certificate = nullptr;
1111 ULONG certificate_length = 0;
1112
1113 HRESULT hr = video_output->StartInitialization(&random_number, &certificate,
1114 &certificate_length);
1115 if (FAILED(hr))
1116 return false;
1117
1118 if (certificate_length != CalculateCertLength(monitor_index))
1119 return false;
1120
1121 for (ULONG i = 0; i < certificate_length; ++i) {
1122 if (certificate[i] != 'A' + monitor_index)
1123 return false;
1124 }
1125
1126 for (ULONG i = 0; i < sizeof(random_number.abRandomNumber); ++i) {
1127 if (random_number.abRandomNumber[i] != '!' + monitor_index)
1128 return false;
1129 }
1130
1131 return true;
1132 }
1133
1134 static bool SendSingleGetInfoRequest(uintptr_t monitor_index,
1135 IOPMVideoOutput* video_output,
1136 const GUID& request,
1137 ULONG data_length,
1138 void* data) {
1139 OPM_GET_INFO_PARAMETERS params = {};
1140 OPM_REQUESTED_INFORMATION requested_information = {};
1141 BYTE* requested_information_ptr =
1142 reinterpret_cast<BYTE*>(&requested_information);
1143 params.guidInformation = request;
1144 params.cbParametersSize = data_length;
1145 memcpy(params.abParameters, data, data_length);
1146 HRESULT hr = video_output->GetInformation(&params, &requested_information);
1147 if (FAILED(hr))
1148 return false;
1149 for (size_t i = 0; i < sizeof(OPM_REQUESTED_INFORMATION); ++i) {
1150 if (requested_information_ptr[i] != '0' + monitor_index)
1151 return false;
1152 }
1153 return true;
1154 }
1155
1156 bool RunTestsOnVideoOutputGetInformation(uintptr_t monitor_index,
1157 IOPMVideoOutput* video_output) {
1158 ULONG dummy = 0;
1159 if (!SendSingleGetInfoRequest(monitor_index, video_output,
1160 OPM_GET_CONNECTOR_TYPE, 0, nullptr)) {
1161 return false;
1162 }
1163 if (!SendSingleGetInfoRequest(monitor_index, video_output,
1164 OPM_GET_SUPPORTED_PROTECTION_TYPES, 0,
1165 nullptr)) {
1166 return false;
1167 }
1168 // These should fail due to invalid parameter sizes.
1169 if (SendSingleGetInfoRequest(monitor_index, video_output,
1170 OPM_GET_CONNECTOR_TYPE, sizeof(dummy), &dummy)) {
1171 return false;
1172 }
1173 if (SendSingleGetInfoRequest(monitor_index, video_output,
1174 OPM_GET_SUPPORTED_PROTECTION_TYPES,
1175 sizeof(dummy), &dummy)) {
1176 return false;
1177 }
1178 ULONG protection_type = OPM_PROTECTION_TYPE_HDCP;
1179 if (!SendSingleGetInfoRequest(monitor_index, video_output,
1180 OPM_GET_ACTUAL_PROTECTION_LEVEL,
1181 sizeof(protection_type), &protection_type)) {
1182 return false;
1183 }
1184 protection_type = OPM_PROTECTION_TYPE_DPCP;
1185 if (!SendSingleGetInfoRequest(monitor_index, video_output,
1186 OPM_GET_ACTUAL_PROTECTION_LEVEL,
1187 sizeof(protection_type), &protection_type)) {
1188 return false;
1189 }
1190 // These should fail as unsupported or invalid parameters.
1191 protection_type = OPM_PROTECTION_TYPE_ACP;
1192 if (SendSingleGetInfoRequest(monitor_index, video_output,
1193 OPM_GET_ACTUAL_PROTECTION_LEVEL,
1194 sizeof(protection_type), &protection_type)) {
1195 return false;
1196 }
1197 if (SendSingleGetInfoRequest(monitor_index, video_output,
1198 OPM_GET_ACTUAL_PROTECTION_LEVEL, 0, nullptr)) {
1199 return false;
1200 }
1201 protection_type = OPM_PROTECTION_TYPE_HDCP;
1202 if (!SendSingleGetInfoRequest(monitor_index, video_output,
1203 OPM_GET_VIRTUAL_PROTECTION_LEVEL,
1204 sizeof(protection_type), &protection_type)) {
1205 return false;
1206 }
1207 protection_type = OPM_PROTECTION_TYPE_DPCP;
1208 if (!SendSingleGetInfoRequest(monitor_index, video_output,
1209 OPM_GET_VIRTUAL_PROTECTION_LEVEL,
1210 sizeof(protection_type), &protection_type)) {
1211 return false;
1212 }
1213 // These should fail as unsupported or invalid parameters.
1214 protection_type = OPM_PROTECTION_TYPE_ACP;
1215 if (SendSingleGetInfoRequest(monitor_index, video_output,
1216 OPM_GET_VIRTUAL_PROTECTION_LEVEL,
1217 sizeof(protection_type), &protection_type)) {
1218 return false;
1219 }
1220 if (SendSingleGetInfoRequest(monitor_index, video_output,
1221 OPM_GET_VIRTUAL_PROTECTION_LEVEL, 0, nullptr)) {
1222 return false;
1223 }
1224 // This should fail with unsupported request.
1225 if (SendSingleGetInfoRequest(monitor_index, video_output, OPM_GET_CODEC_INFO,
1226 0, nullptr)) {
1227 return false;
1228 }
1229 return true;
1230 }
1231
1232 int RunTestsOnVideoOutput(uintptr_t monitor_index,
1233 IOPMVideoOutput* video_output) {
1234 if (!RunTestsOnVideoOutputStartInitialization(monitor_index, video_output))
1235 return SBOX_TEST_FIRST_ERROR;
1236
1237 if (!RunTestsOnVideoOutputFinishInitialization(monitor_index, video_output))
1238 return SBOX_TEST_SECOND_ERROR;
1239
1240 if (!RunTestsOnVideoOutputConfigure(monitor_index, video_output))
1241 return SBOX_TEST_THIRD_ERROR;
1242
1243 if (!RunTestsOnVideoOutputGetInformation(monitor_index, video_output))
1244 return SBOX_TEST_FOURTH_ERROR;
1245
1246 return SBOX_TEST_SUCCEEDED;
1247 }
1248
1249 SBOX_TESTS_COMMAND int CheckWin8OPMApis(int argc, wchar_t** argv) {
1250 std::map<HMONITOR, base::string16> monitors = GetTestMonitors();
1251 for (const auto& monitor : monitors) {
1252 ULONG output_count = 0;
1253 IOPMVideoOutput** outputs = nullptr;
1254 uintptr_t monitor_index = reinterpret_cast<uintptr_t>(monitor.first) & 0xF;
1255 HRESULT hr = OPMGetVideoOutputsFromHMONITOR(
1256 monitor.first, OPM_VOS_OPM_SEMANTICS, &output_count, &outputs);
1257 if (monitor_index > 4) {
1258 // These should fail because the certificate is too large.
1259 if (SUCCEEDED(hr))
1260 return SBOX_TEST_FIRST_ERROR;
1261 continue;
1262 }
1263 if (FAILED(hr))
1264 return SBOX_TEST_SECOND_ERROR;
1265 if (output_count != monitor_index - 1)
1266 return SBOX_TEST_THIRD_ERROR;
1267 for (ULONG output_index = 0; output_index < output_count; ++output_index) {
1268 int result = RunTestsOnVideoOutput(monitor_index, outputs[output_index]);
1269 outputs[output_index]->Release();
1270 if (result != SBOX_TEST_SUCCEEDED)
1271 return result;
1272 }
1273 ::CoTaskMemFree(outputs);
1274 }
1275 return SBOX_TEST_SUCCEEDED;
1276 }
1277
1278 // This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation on
1279 // the target process causes the launch to fail in process initialization.
1280 // The test process itself links against user32/gdi32.
1281 TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownFailure) {
1282 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1283 return;
1284
1285 TestRunner runner;
1286 sandbox::TargetPolicy* policy = runner.GetPolicy();
1287
1288 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE),
1289 SBOX_ALL_OK);
1290 EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown"));
1291 }
1292
1293 // This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation
1294 // along with the policy to fake user32 and gdi32 initialization successfully
1295 // launches the target process.
1296 // The test process itself links against user32/gdi32.
1297 TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownSuccess) {
1298 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1299 return;
1300
1301 TestRunner runner;
1302 sandbox::TargetPolicy* policy = runner.GetPolicy();
1303 ProcessMitigationsWin32KLockdownPolicy::SetOverrideForTestCallback(
1304 FunctionOverrideForTest);
1305
1306 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE),
1307 SBOX_ALL_OK);
1308 EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN,
1309 sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL),
1310 sandbox::SBOX_ALL_OK);
1311 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown"));
1312 EXPECT_NE(SBOX_TEST_SUCCEEDED,
1313 runner.RunTest(L"CheckWin8MonitorsRedirection"));
1314 EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8MonitorInfo"));
1315 EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8OPMApis"));
1316 }
1317
1318 // This test validates the even though we're running under win32k lockdown
1319 // we can use the IPC redirection to enumerate the list of monitors.
1320 TEST(ProcessMitigationsTest, CheckWin8Win32KRedirection) {
1321 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1322 return;
1323
1324 TestRunner runner;
1325 sandbox::TargetPolicy* policy = runner.GetPolicy();
1326 ProcessMitigationsWin32KLockdownPolicy::SetOverrideForTestCallback(
1327 FunctionOverrideForTest);
1328
1329 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE),
1330 SBOX_ALL_OK);
1331 EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN,
1332 sandbox::TargetPolicy::IMPLEMENT_OPM_APIS, NULL),
1333 sandbox::SBOX_ALL_OK);
1334 policy->SetEnableOPMRedirection();
1335 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown"));
1336 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
1337 runner.RunTest(L"CheckWin8MonitorsRedirection"));
1338 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8MonitorInfo"));
1339 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8OPMApis"));
1340 }
1341
1342 //------------------------------------------------------------------------------
1343 // Disable extension points (MITIGATION_EXTENSION_POINT_DISABLE).
1344 // >= Win8
1345 //------------------------------------------------------------------------------
1346 SBOX_TESTS_COMMAND int CheckWin8ExtensionPointSetting(int argc,
1347 wchar_t** argv) {
1348 get_process_mitigation_policy =
1349 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress(
1350 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy"));
1351 if (!get_process_mitigation_policy)
1352 return SBOX_TEST_NOT_FOUND;
1353
1354 if (!CheckWin8ExtensionPointPolicy())
1355 return SBOX_TEST_FIRST_ERROR;
1356 return SBOX_TEST_SUCCEEDED;
1357 }
1358
1359 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE
1360 // mitigation enables the setting on a process.
1361 TEST(ProcessMitigationsTest, CheckWin8ExtensionPointPolicySuccess) {
1362 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1363 return;
1364
1365 TestRunner runner;
1366 sandbox::TargetPolicy* policy = runner.GetPolicy();
1367
1368 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_EXTENSION_POINT_DISABLE),
1369 SBOX_ALL_OK);
1370 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
1371 runner.RunTest(L"CheckWin8ExtensionPointSetting"));
1372 }
1373
1374 // This test validates that a "legitimate" global hook CAN be set on the
1375 // sandboxed proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE
1376 // mitigation is not set.
1377 //
1378 // MANUAL testing only.
1379 TEST(ProcessMitigationsTest,
1380 DISABLED_CheckWin8ExtensionPoint_GlobalHook_Success) {
1381 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1382 return;
1383
1384 HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex);
1385 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE);
1386 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout));
1387
1388 // (is_success_test, global_hook)
1389 TestWin8ExtensionPointHookWrapper(true, true);
1390
1391 EXPECT_TRUE(::ReleaseMutex(mutex));
1392 EXPECT_TRUE(::CloseHandle(mutex));
1393 }
1394
1395 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE
1396 // mitigation prevents a global hook on WinProc.
1397 //
1398 // MANUAL testing only.
1399 TEST(ProcessMitigationsTest,
1400 DISABLED_CheckWin8ExtensionPoint_GlobalHook_Failure) {
1401 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1402 return;
1403
1404 HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex);
1405 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE);
1406 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout));
1407
1408 // (is_success_test, global_hook)
1409 TestWin8ExtensionPointHookWrapper(false, true);
1410
1411 EXPECT_TRUE(::ReleaseMutex(mutex));
1412 EXPECT_TRUE(::CloseHandle(mutex));
1413 }
1414
1415 // This test validates that a "legitimate" hook CAN be set on the sandboxed
1416 // proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set.
1417 //
1418 // MANUAL testing only.
1419 TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Success) {
1420 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1421 return;
1422
1423 HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex);
1424 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE);
1425 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout));
1426
1427 // (is_success_test, global_hook)
1428 TestWin8ExtensionPointHookWrapper(true, false);
1429
1430 EXPECT_TRUE(::ReleaseMutex(mutex));
1431 EXPECT_TRUE(::CloseHandle(mutex));
1432 }
1433
1434 // *** Important: MITIGATION_EXTENSION_POINT_DISABLE does NOT prevent
1435 // hooks targetted at a specific thread id. It only prevents
1436 // global hooks. So this test does NOT actually expect the hook
1437 // to fail (see TestWin8ExtensionPointHookWrapper function) even
1438 // with the mitigation on.
1439 //
1440 // MANUAL testing only.
1441 TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Failure) {
1442 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1443 return;
1444
1445 HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex);
1446 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE);
1447 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout));
1448
1449 // (is_success_test, global_hook)
1450 TestWin8ExtensionPointHookWrapper(false, false);
1451
1452 EXPECT_TRUE(::ReleaseMutex(mutex));
1453 EXPECT_TRUE(::CloseHandle(mutex));
1454 }
1455
1456 // This test validates that an AppInit Dll CAN be added to a target
1457 // WinProc if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set.
1458 //
1459 // MANUAL testing only.
1460 // Must run this test as admin/elevated.
1461 TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Success) {
1462 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1463 return;
1464
1465 HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex);
1466 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE);
1467 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout));
1468
1469 TestWin8ExtensionPointAppInitWrapper(true);
1470
1471 EXPECT_TRUE(::ReleaseMutex(mutex));
1472 EXPECT_TRUE(::CloseHandle(mutex));
1473 }
1474
1475 // This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE
1476 // mitigation prevents the loading of any AppInit Dll into WinProc.
1477 //
1478 // MANUAL testing only.
1479 // Must run this test as admin/elevated.
1480 TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Failure) {
1481 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1482 return;
1483
1484 HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex);
1485 EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE);
1486 EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout));
1487
1488 TestWin8ExtensionPointAppInitWrapper(false);
1489
1490 EXPECT_TRUE(::ReleaseMutex(mutex));
1491 EXPECT_TRUE(::CloseHandle(mutex));
1492 }
1493
1494 //------------------------------------------------------------------------------
1495 // Disable non-system font loads (MITIGATION_NONSYSTEM_FONT_DISABLE)
1496 // >= Win10
1497 //------------------------------------------------------------------------------
1498
1499 SBOX_TESTS_COMMAND int CheckWin10FontLockDown(int argc, wchar_t** argv) {
1500 get_process_mitigation_policy =
1501 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress(
1502 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy"));
1503 if (!get_process_mitigation_policy)
1504 return SBOX_TEST_NOT_FOUND;
1505
1506 if (!CheckWin10FontPolicy())
1507 return SBOX_TEST_FIRST_ERROR;
1508 return SBOX_TEST_SUCCEEDED;
1509 }
1510
1511 SBOX_TESTS_COMMAND int CheckWin10FontLoad(int argc, wchar_t** argv) {
1512 if (argc < 1)
1513 return SBOX_TEST_INVALID_PARAMETER;
1514
1515 HMODULE gdi_module = ::LoadLibraryW(L"gdi32.dll");
1516 if (!gdi_module)
1517 return SBOX_TEST_NOT_FOUND;
1518
1519 AddFontMemResourceExFunction add_font_mem_resource =
1520 reinterpret_cast<AddFontMemResourceExFunction>(
1521 ::GetProcAddress(gdi_module, "AddFontMemResourceEx"));
1522
1523 RemoveFontMemResourceExFunction rem_font_mem_resource =
1524 reinterpret_cast<RemoveFontMemResourceExFunction>(
1525 ::GetProcAddress(gdi_module, "RemoveFontMemResourceEx"));
1526
1527 if (!add_font_mem_resource || !rem_font_mem_resource)
1528 return SBOX_TEST_NOT_FOUND;
1529
1530 // Open font file passed in as an argument.
1531 base::File file(base::FilePath(argv[0]),
1532 base::File::FLAG_OPEN | base::File::FLAG_READ);
1533 if (!file.IsValid())
1534 // Failed to open the font file passed in.
1535 return SBOX_TEST_NOT_FOUND;
1536
1537 std::vector<char> font_data;
1538 int64_t len = file.GetLength();
1539 if (len < 0)
1540 return SBOX_TEST_NOT_FOUND;
1541 font_data.resize(len);
1542
1543 int read = file.Read(0, &font_data[0], len);
1544 file.Close();
1545
1546 if (read != len)
1547 return SBOX_TEST_NOT_FOUND;
1548
1549 DWORD font_count = 0;
1550 HANDLE font_handle = add_font_mem_resource(
1551 &font_data[0], static_cast<DWORD>(font_data.size()), NULL, &font_count);
1552
1553 if (font_handle) {
1554 rem_font_mem_resource(font_handle);
1555 return SBOX_TEST_SUCCEEDED;
1556 }
1557
1558 return SBOX_TEST_FAILED;
1559 }
1560
1561 // This test validates that setting the MITIGATION_NON_SYSTEM_FONTS_DISABLE
1562 // mitigation enables the setting on a process.
1563 TEST(ProcessMitigationsTest, CheckWin10NonSystemFontLockDownPolicySuccess) {
1564 if (base::win::GetVersion() < base::win::VERSION_WIN10)
1565 return;
1566
1567 TestRunner runner;
1568 sandbox::TargetPolicy* policy = runner.GetPolicy();
1569
1570 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_NONSYSTEM_FONT_DISABLE),
1571 SBOX_ALL_OK);
1572 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin10FontLockDown"));
1573 }
1574
1575 // This test validates that we can load a non-system font
1576 // if the MITIGATION_NON_SYSTEM_FONTS_DISABLE
1577 // mitigation is NOT set.
1578 TEST(ProcessMitigationsTest, CheckWin10NonSystemFontLockDownLoadSuccess) {
1579 if (base::win::GetVersion() < base::win::VERSION_WIN10)
1580 return;
1581
1582 base::FilePath font_path;
1583 EXPECT_TRUE(base::PathService::Get(base::DIR_WINDOWS_FONTS, &font_path));
1584 // Arial font should always be available
1585 font_path = font_path.Append(L"arial.ttf");
1586
1587 TestRunner runner;
1588 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
1589 font_path.value().c_str()));
1590
1591 std::wstring test_command = L"CheckWin10FontLoad \"";
1592 test_command += font_path.value().c_str();
1593 test_command += L"\"";
1594 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
1595 }
1596
1597 // This test validates that setting the MITIGATION_NON_SYSTEM_FONTS_DISABLE
1598 // mitigation prevents the loading of a non-system font.
1599 TEST(ProcessMitigationsTest, CheckWin10NonSystemFontLockDownLoadFailure) {
1600 if (base::win::GetVersion() < base::win::VERSION_WIN10)
1601 return;
1602
1603 base::FilePath font_path;
1604 EXPECT_TRUE(base::PathService::Get(base::DIR_WINDOWS_FONTS, &font_path));
1605 // Arial font should always be available
1606 font_path = font_path.Append(L"arial.ttf");
1607
1608 TestRunner runner;
1609 sandbox::TargetPolicy* policy = runner.GetPolicy();
1610 EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY,
1611 font_path.value().c_str()));
1612
1613 // Turn on the non-system font disable mitigation.
1614 EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_NONSYSTEM_FONT_DISABLE),
1615 SBOX_ALL_OK);
1616
1617 std::wstring test_command = L"CheckWin10FontLoad \"";
1618 test_command += font_path.value().c_str();
1619 test_command += L"\"";
1620
1621 EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(test_command.c_str()));
1622 }
1623
1624 //------------------------------------------------------------------------------
1625 // Disable image load from remote devices (MITIGATION_IMAGE_LOAD_NO_REMOTE).
1626 // >= Win10_TH2
1627 //------------------------------------------------------------------------------
1628
1629 SBOX_TESTS_COMMAND int CheckWin10ImageLoadNoRemote(int argc, wchar_t** argv) {
1630 get_process_mitigation_policy =
1631 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress(
1632 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy"));
1633 if (!get_process_mitigation_policy)
1634 return SBOX_TEST_NOT_FOUND;
1635
1636 if (!CheckWin10ImageLoadNoRemotePolicy())
1637 return SBOX_TEST_FIRST_ERROR;
1638 return SBOX_TEST_SUCCEEDED;
1639 }
1640
1641 // This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE
1642 // mitigation enables the setting on a process.
1643 TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoRemotePolicySuccess) {
1644 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
1645 return;
1646
1647 TestRunner runner;
1648 sandbox::TargetPolicy* policy = runner.GetPolicy();
1649
1650 EXPECT_EQ(
1651 policy->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE),
1652 SBOX_ALL_OK);
1653 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
1654 runner.RunTest(L"CheckWin10ImageLoadNoRemote"));
1655 }
1656
1657 // This test validates that we CAN create a new process from
1658 // a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE
1659 // mitigation is NOT set.
1660 //
1661 // MANUAL testing only.
1662 TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) {
1663 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
1664 return;
1665
1666 TestWin10ImageLoadRemote(true);
1667 }
1668
1669 // This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE
1670 // mitigation prevents creating a new process from a remote
1671 // UNC device.
1672 //
1673 // MANUAL testing only.
1674 TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) {
1675 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
1676 return;
1677
1678 TestWin10ImageLoadRemote(false);
1679 }
1680
1681 //------------------------------------------------------------------------------
1682 // Disable image load when "mandatory low label" (integrity level).
1683 // (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL)
1684 // >= Win10_TH2
1685 //------------------------------------------------------------------------------
1686
1687 SBOX_TESTS_COMMAND int CheckWin10ImageLoadNoLowLabel(int argc, wchar_t** argv) {
1688 get_process_mitigation_policy =
1689 reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress(
1690 ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy"));
1691 if (!get_process_mitigation_policy)
1692 return SBOX_TEST_NOT_FOUND;
1693
1694 if (!CheckWin10ImageLoadNoLowLabelPolicy())
1695 return SBOX_TEST_FIRST_ERROR;
1696 return SBOX_TEST_SUCCEEDED;
1697 }
1698
1699 // This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
1700 // mitigation enables the setting on a process.
1701 TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelPolicySuccess) {
1702 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
1703 return;
1704
1705 TestRunner runner;
1706 sandbox::TargetPolicy* policy = runner.GetPolicy();
1707
1708 EXPECT_EQ(
1709 policy->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
1710 SBOX_ALL_OK);
1711 EXPECT_EQ(SBOX_TEST_SUCCEEDED,
1712 runner.RunTest(L"CheckWin10ImageLoadNoLowLabel"));
1713 }
1714
1715 // This test validates that we CAN create a new process with
1716 // low mandatory label (IL), if the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
1717 // mitigation is NOT set.
1718 TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelSuccess) {
1719 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
1720 return;
1721
1722 TestWin10ImageLoadLowLabel(true);
1723 }
1724
1725 // This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
1726 // mitigation prevents creating a new process with low mandatory label (IL).
1727 TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelFailure) {
1728 if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2)
1729 return;
1730
1731 TestWin10ImageLoadLowLabel(false);
1732 }
1733
1734 //------------------------------------------------------------------------------
1735 // Disable child process creation.
1736 // - JobLevel <= JOB_LIMITED_USER (on < WIN10_TH2).
1737 // - JobLevel <= JOB_LIMITED_USER which also triggers setting
1738 // PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY to
1739 // PROCESS_CREATION_CHILD_PROCESS_RESTRICTED in
1740 // BrokerServicesBase::SpawnTarget (on >= WIN10_TH2).
1741 //------------------------------------------------------------------------------
1742
1743 // This test validates that we can spawn a child process if
1744 // MITIGATION_CHILD_PROCESS_CREATION_RESTRICTED mitigation is
1745 // not set.
1746 TEST(ProcessMitigationsTest, CheckChildProcessSuccess) {
1747 TestRunner runner;
1748 sandbox::TargetPolicy* policy = runner.GetPolicy();
1749
1750 // Set a policy that would normally allow for process creation.
1751 policy->SetJobLevel(JOB_INTERACTIVE, 0);
1752 policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED);
1753 runner.SetDisableCsrss(false);
1754
1755 base::FilePath cmd;
1756 EXPECT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &cmd));
1757 cmd = cmd.Append(L"calc.exe");
1758
1759 std::wstring test_command = L"TestChildProcess ";
1760 test_command += cmd.value().c_str();
1761
1762 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
1763 }
1764
1765 // This test validates that setting the
1766 // MITIGATION_CHILD_PROCESS_CREATION_RESTRICTED mitigation prevents
1767 // the spawning of child processes.
1768 TEST(ProcessMitigationsTest, CheckChildProcessFailure) {
1769 TestRunner runner;
1770 sandbox::TargetPolicy* policy = runner.GetPolicy();
1771
1772 // Now set the job level to be <= JOB_LIMITED_USER
1773 // and ensure we can no longer create a child process.
1774 policy->SetJobLevel(JOB_LIMITED_USER, 0);
1775 policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED);
1776 runner.SetDisableCsrss(false);
1777
1778 base::FilePath cmd;
1779 EXPECT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &cmd));
1780 cmd = cmd.Append(L"calc.exe");
1781
1782 std::wstring test_command = L"TestChildProcess ";
1783 test_command += cmd.value().c_str();
1784
1785 EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(test_command.c_str()));
1786 }
1787
1788 // This test validates that when the sandboxed target within a job spawns a
1789 // child process and the target process exits abnormally, the broker correctly
1790 // handles the JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS message.
1791 // Because this involves spawning a child process from the target process and is
1792 // very similar to the above CheckChildProcess* tests, this test is here rather
1793 // than elsewhere closer to the other Job tests.
1794 TEST(ProcessMitigationsTest, CheckChildProcessAbnormalExit) {
1795 TestRunner runner;
1796 sandbox::TargetPolicy* policy = runner.GetPolicy();
1797
1798 // Set a policy that would normally allow for process creation.
1799 policy->SetJobLevel(JOB_INTERACTIVE, 0);
1800 policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED);
1801 runner.SetDisableCsrss(false);
1802
1803 base::FilePath cmd;
1804 EXPECT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &cmd));
1805 cmd = cmd.Append(L"calc.exe");
1806
1807 std::wstring test_command(base::StringPrintf(L"TestChildProcess %ls 0x%08X",
1808 cmd.value().c_str(),
1809 STATUS_ACCESS_VIOLATION));
1810
1811 EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
1812 }
1813
1814 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/src/process_mitigations_imageload_unittest.cc ('k') | sandbox/win/src/process_mitigations_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698