Index: sandbox/win/src/process_mitigations_test.cc |
diff --git a/sandbox/win/src/process_mitigations_test.cc b/sandbox/win/src/process_mitigations_test.cc |
deleted file mode 100644 |
index 1e6b3420a0c2542db8cdc5a6fcd7e53166021dc9..0000000000000000000000000000000000000000 |
--- a/sandbox/win/src/process_mitigations_test.cc |
+++ /dev/null |
@@ -1,1814 +0,0 @@ |
-// Copyright 2011 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "sandbox/win/src/process_mitigations.h" |
- |
-#include <d3d9.h> |
-#include <initguid.h> |
-#include <opmapi.h> |
-#include <psapi.h> |
-#include <windows.h> |
- |
-#include <map> |
-#include <string> |
- |
-#include "base/command_line.h" |
-#include "base/files/file_util.h" |
-#include "base/files/scoped_temp_dir.h" |
-#include "base/memory/ref_counted.h" |
-#include "base/path_service.h" |
-#include "base/process/launch.h" |
-#include "base/scoped_native_library.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/test/test_timeouts.h" |
-#include "base/win/registry.h" |
-#include "base/win/scoped_handle.h" |
-#include "base/win/startup_information.h" |
-#include "base/win/win_util.h" |
-#include "base/win/windows_version.h" |
-#include "sandbox/win/src/nt_internals.h" |
-#include "sandbox/win/src/process_mitigations_win32k_policy.h" |
-#include "sandbox/win/src/sandbox.h" |
-#include "sandbox/win/src/sandbox_factory.h" |
-#include "sandbox/win/src/target_services.h" |
-#include "sandbox/win/tests/common/controller.h" |
-#include "sandbox/win/tests/integration_tests/integration_tests_common.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-namespace { |
- |
-// Timeouts for synchronization. |
-#define event_timeout \ |
- static_cast<DWORD>((TestTimeouts::action_timeout()).InMillisecondsRoundedUp()) |
- |
-// API defined in winbase.h. |
-typedef decltype(GetProcessDEPPolicy)* GetProcessDEPPolicyFunction; |
- |
-// API defined in processthreadsapi.h. |
-typedef decltype( |
- GetProcessMitigationPolicy)* GetProcessMitigationPolicyFunction; |
-GetProcessMitigationPolicyFunction get_process_mitigation_policy; |
- |
-// APIs defined in wingdi.h. |
-typedef decltype(AddFontMemResourceEx)* AddFontMemResourceExFunction; |
-typedef decltype(RemoveFontMemResourceEx)* RemoveFontMemResourceExFunction; |
- |
-// APIs defined in integration_tests_common.h |
-typedef decltype(WasHookCalled)* WasHookCalledFunction; |
-typedef decltype(SetHook)* SetHookFunction; |
- |
-#if !defined(_WIN64) |
-bool CheckWin8DepPolicy() { |
- PROCESS_MITIGATION_DEP_POLICY policy = {}; |
- if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessDEPPolicy, |
- &policy, sizeof(policy))) { |
- return false; |
- } |
- return policy.Enable && policy.Permanent; |
-} |
-#endif // !defined(_WIN64) |
- |
-bool CheckWin8AslrPolicy() { |
- PROCESS_MITIGATION_ASLR_POLICY policy = {}; |
- if (!get_process_mitigation_policy(::GetCurrentProcess(), ProcessASLRPolicy, |
- &policy, sizeof(policy))) { |
- return false; |
- } |
- return policy.EnableForceRelocateImages && policy.DisallowStrippedImages; |
-} |
- |
-bool CheckWin8StrictHandlePolicy() { |
- PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY policy = {}; |
- if (!get_process_mitigation_policy(::GetCurrentProcess(), |
- ProcessStrictHandleCheckPolicy, &policy, |
- sizeof(policy))) { |
- return false; |
- } |
- return policy.RaiseExceptionOnInvalidHandleReference && |
- policy.HandleExceptionsPermanentlyEnabled; |
-} |
- |
-bool CheckWin8Win32CallPolicy() { |
- PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; |
- if (!get_process_mitigation_policy(::GetCurrentProcess(), |
- ProcessSystemCallDisablePolicy, &policy, |
- sizeof(policy))) { |
- return false; |
- } |
- return policy.DisallowWin32kSystemCalls; |
-} |
- |
-bool CheckWin8ExtensionPointPolicy() { |
- PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY policy = {}; |
- if (!get_process_mitigation_policy(::GetCurrentProcess(), |
- ProcessExtensionPointDisablePolicy, |
- &policy, sizeof(policy))) { |
- return false; |
- } |
- return policy.DisableExtensionPoints; |
-} |
- |
-bool CheckWin10FontPolicy() { |
- PROCESS_MITIGATION_FONT_DISABLE_POLICY policy = {}; |
- if (!get_process_mitigation_policy(::GetCurrentProcess(), |
- ProcessFontDisablePolicy, &policy, |
- sizeof(policy))) { |
- return false; |
- } |
- return policy.DisableNonSystemFonts; |
-} |
- |
-bool CheckWin10ImageLoadNoRemotePolicy() { |
- PROCESS_MITIGATION_IMAGE_LOAD_POLICY policy = {}; |
- if (!get_process_mitigation_policy(::GetCurrentProcess(), |
- ProcessImageLoadPolicy, &policy, |
- sizeof(policy))) { |
- return false; |
- } |
- return policy.NoRemoteImages; |
-} |
- |
-// Spawn Windows process (with or without mitigation enabled). |
-bool SpawnWinProc(PROCESS_INFORMATION* pi, bool success_test, HANDLE* event) { |
- base::win::StartupInformation startup_info; |
- DWORD creation_flags = 0; |
- |
- if (!success_test) { |
- DWORD64 flags = |
- PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; |
- // This test only runs on >= Win8, so don't have to handle |
- // illegal 64-bit flags on 32-bit <= Win7. |
- size_t flags_size = sizeof(flags); |
- |
- if (!startup_info.InitializeProcThreadAttributeList(1) || |
- !startup_info.UpdateProcThreadAttribute( |
- PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &flags, flags_size)) { |
- ADD_FAILURE(); |
- return false; |
- } |
- creation_flags = EXTENDED_STARTUPINFO_PRESENT; |
- } |
- |
- // Command line must be writable. |
- base::string16 cmd_writeable(g_winproc_file); |
- |
- if (!::CreateProcessW(NULL, &cmd_writeable[0], NULL, NULL, FALSE, |
- creation_flags, NULL, NULL, startup_info.startup_info(), |
- pi)) { |
- ADD_FAILURE(); |
- return false; |
- } |
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(*event, event_timeout)); |
- |
- return true; |
-} |
- |
-//------------------------------------------------------------------------------ |
-// 1. Spawn a Windows process (with or without mitigation enabled). |
-// 2. Load the hook Dll locally. |
-// 3. Create a global named event for the hook to trigger. |
-// 4. Start the hook (for the specific WinProc or globally). |
-// 5. Send a keystroke event. |
-// 6. Ask the hook Dll if it received a hook callback. |
-// 7. Cleanup the hooking. |
-// 8. Signal the Windows process to shutdown. |
-// |
-// Do NOT use any ASSERTs in this function. Cleanup required. |
-//------------------------------------------------------------------------------ |
-void TestWin8ExtensionPointHookWrapper(bool is_success_test, bool global_hook) { |
- // Set up a couple global events that this test will use. |
- HANDLE winproc_event = ::CreateEventW(NULL, FALSE, FALSE, g_winproc_event); |
- if (winproc_event == NULL || winproc_event == INVALID_HANDLE_VALUE) { |
- ADD_FAILURE(); |
- return; |
- } |
- base::win::ScopedHandle scoped_winproc_event(winproc_event); |
- |
- HANDLE hook_event = ::CreateEventW(NULL, FALSE, FALSE, g_hook_event); |
- if (hook_event == NULL || hook_event == INVALID_HANDLE_VALUE) { |
- ADD_FAILURE(); |
- return; |
- } |
- base::win::ScopedHandle scoped_hook_event(hook_event); |
- |
- // 1. Spawn WinProc. |
- PROCESS_INFORMATION proc_info = {}; |
- if (!SpawnWinProc(&proc_info, is_success_test, &winproc_event)) |
- return; |
- |
- // From this point on, no return on failure. Cleanup required. |
- bool all_good = true; |
- |
- // 2. Load the hook DLL. |
- base::FilePath hook_dll_path(g_hook_dll_file); |
- base::ScopedNativeLibrary dll(hook_dll_path); |
- EXPECT_TRUE(dll.is_valid()); |
- |
- HOOKPROC hook_proc = |
- reinterpret_cast<HOOKPROC>(dll.GetFunctionPointer(g_hook_handler_func)); |
- WasHookCalledFunction was_hook_called = |
- reinterpret_cast<WasHookCalledFunction>( |
- dll.GetFunctionPointer(g_was_hook_called_func)); |
- SetHookFunction set_hook = reinterpret_cast<SetHookFunction>( |
- dll.GetFunctionPointer(g_set_hook_func)); |
- if (!hook_proc || !was_hook_called || !set_hook) { |
- ADD_FAILURE(); |
- all_good = false; |
- } |
- |
- // 3. Try installing the hook (either on a remote target thread, |
- // or globally). |
- HHOOK hook = nullptr; |
- if (all_good) { |
- DWORD target = 0; |
- if (!global_hook) |
- target = proc_info.dwThreadId; |
- hook = ::SetWindowsHookExW(WH_KEYBOARD, hook_proc, dll.get(), target); |
- if (!hook) { |
- ADD_FAILURE(); |
- all_good = false; |
- } else |
- // Pass the hook DLL the hook handle. |
- set_hook(hook); |
- } |
- |
- // 4. Inject a keyboard event. |
- if (all_good) { |
- // Note: that PostThreadMessage and SendMessage APIs will not deliver |
- // a keystroke in such a way that triggers a "legitimate" hook. |
- // Have to use targetless SendInput or keybd_event. The latter is |
- // less code and easier to work with. |
- keybd_event(VkKeyScan(L'A'), 0, 0, 0); |
- keybd_event(VkKeyScan(L'A'), 0, KEYEVENTF_KEYUP, 0); |
- // Give it a chance to hit the hook handler... |
- ::WaitForSingleObject(hook_event, event_timeout); |
- |
- // 5. Did the hook get hit? Was it expected to? |
- if (global_hook) |
- EXPECT_EQ((is_success_test ? true : false), was_hook_called()); |
- else |
- // ***IMPORTANT: when targeting a specific thread id, the |
- // PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE |
- // mitigation does NOT disable the hook API. It ONLY |
- // stops global hooks from running in a process. Hence, |
- // the hook will hit (TRUE) even in the "failure" |
- // case for a non-global/targeted hook. |
- EXPECT_EQ((is_success_test ? true : true), was_hook_called()); |
- } |
- |
- // 6. Disable hook. |
- if (hook) |
- EXPECT_TRUE(::UnhookWindowsHookEx(hook)); |
- |
- // 7. Trigger shutdown of WinProc. |
- if (proc_info.hProcess) { |
- if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { |
- // Note: The combination/perfect-storm of a Global Hook, in a |
- // WinProc that has the EXTENSION_POINT_DISABLE mitigation ON, and the |
- // use of the SendInput or keybd_event API to inject a keystroke, |
- // results in the target becoming unresponsive. If any one of these |
- // states are changed, the problem does not occur. This means the WM_QUIT |
- // message is not handled and the call to WaitForSingleObject times out. |
- // Therefore not checking the return val. |
- ::WaitForSingleObject(winproc_event, event_timeout); |
- } else { |
- // Ensure no strays. |
- ::TerminateProcess(proc_info.hProcess, 0); |
- ADD_FAILURE(); |
- } |
- EXPECT_TRUE(::CloseHandle(proc_info.hThread)); |
- EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); |
- } |
-} |
- |
-//------------------------------------------------------------------------------ |
-// 1. Set up the AppInit Dll in registry settings. (Enable) |
-// 2. Spawn a Windows process (with or without mitigation enabled). |
-// 3. Check if the AppInit Dll got loaded in the Windows process or not. |
-// 4. Signal the Windows process to shutdown. |
-// 5. Restore original reg settings. |
-// |
-// Do NOT use any ASSERTs in this function. Cleanup required. |
-//------------------------------------------------------------------------------ |
-void TestWin8ExtensionPointAppInitWrapper(bool is_success_test) { |
- // 0.5 Get path of current module. The appropriate build of the |
- // AppInit DLL will be in the same directory (and the |
- // full path is needed for reg). |
- wchar_t path[MAX_PATH]; |
- if (!::GetModuleFileNameW(NULL, path, MAX_PATH)) { |
- ADD_FAILURE(); |
- return; |
- } |
- // Only want the directory. Switch file name for the AppInit DLL. |
- base::FilePath full_dll_path(path); |
- full_dll_path = full_dll_path.DirName(); |
- full_dll_path = full_dll_path.Append(g_hook_dll_file); |
- wchar_t* non_const = const_cast<wchar_t*>(full_dll_path.value().c_str()); |
- // Now make sure the path is in "short-name" form for registry. |
- DWORD length = ::GetShortPathNameW(non_const, NULL, 0); |
- std::vector<wchar_t> short_name(length); |
- if (!::GetShortPathNameW(non_const, &short_name[0], length)) { |
- ADD_FAILURE(); |
- return; |
- } |
- |
- // 1. Reg setup. |
- const wchar_t* app_init_reg_path = |
- L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"; |
- const wchar_t* dlls_value_name = L"AppInit_DLLs"; |
- const wchar_t* enabled_value_name = L"LoadAppInit_DLLs"; |
- const wchar_t* signing_value_name = L"RequireSignedAppInit_DLLs"; |
- std::wstring orig_dlls; |
- std::wstring new_dlls; |
- DWORD orig_enabled_value = 0; |
- DWORD orig_signing_value = 0; |
- base::win::RegKey app_init_key(HKEY_LOCAL_MACHINE, app_init_reg_path, |
- KEY_QUERY_VALUE | KEY_SET_VALUE); |
- // Backup the existing settings. |
- if (!app_init_key.Valid() || !app_init_key.HasValue(dlls_value_name) || |
- !app_init_key.HasValue(enabled_value_name) || |
- ERROR_SUCCESS != app_init_key.ReadValue(dlls_value_name, &orig_dlls) || |
- ERROR_SUCCESS != |
- app_init_key.ReadValueDW(enabled_value_name, &orig_enabled_value)) { |
- ADD_FAILURE(); |
- return; |
- } |
- if (app_init_key.HasValue(signing_value_name)) { |
- if (ERROR_SUCCESS != |
- app_init_key.ReadValueDW(signing_value_name, &orig_signing_value)) { |
- ADD_FAILURE(); |
- return; |
- } |
- } |
- |
- // Set the new settings (obviously requires local admin privileges). |
- new_dlls = orig_dlls; |
- if (!orig_dlls.empty()) |
- new_dlls.append(L","); |
- new_dlls.append(short_name.data()); |
- |
- // From this point on, no return on failure. Cleanup required. |
- bool all_good = true; |
- |
- if (app_init_key.HasValue(signing_value_name)) { |
- if (ERROR_SUCCESS != |
- app_init_key.WriteValue(signing_value_name, static_cast<DWORD>(0))) { |
- ADD_FAILURE(); |
- all_good = false; |
- } |
- } |
- if (ERROR_SUCCESS != |
- app_init_key.WriteValue(dlls_value_name, new_dlls.c_str()) || |
- ERROR_SUCCESS != |
- app_init_key.WriteValue(enabled_value_name, static_cast<DWORD>(1))) { |
- ADD_FAILURE(); |
- all_good = false; |
- } |
- |
- // 2. Spawn WinProc. |
- HANDLE winproc_event = INVALID_HANDLE_VALUE; |
- base::win::ScopedHandle scoped_event; |
- PROCESS_INFORMATION proc_info = {}; |
- if (all_good) { |
- winproc_event = ::CreateEventW(NULL, FALSE, FALSE, g_winproc_event); |
- if (winproc_event == NULL || winproc_event == INVALID_HANDLE_VALUE) { |
- ADD_FAILURE(); |
- all_good = false; |
- } else { |
- scoped_event.Set(winproc_event); |
- if (!SpawnWinProc(&proc_info, is_success_test, &winproc_event)) |
- all_good = false; |
- } |
- } |
- |
- // 3. Check loaded modules in WinProc to see if the AppInit dll is loaded. |
- bool dll_loaded = false; |
- if (all_good) { |
- std::vector<HMODULE>(modules); |
- if (!base::win::GetLoadedModulesSnapshot(proc_info.hProcess, &modules)) { |
- ADD_FAILURE(); |
- all_good = false; |
- } else { |
- for (HMODULE module : modules) { |
- wchar_t name[MAX_PATH] = {}; |
- if (::GetModuleFileNameExW(proc_info.hProcess, module, name, |
- MAX_PATH) && |
- ::wcsstr(name, g_hook_dll_file)) { |
- // Found it. |
- dll_loaded = true; |
- break; |
- } |
- } |
- } |
- } |
- |
- // Was the test result as expected? |
- if (all_good) |
- EXPECT_EQ((is_success_test ? true : false), dll_loaded); |
- |
- // 4. Trigger shutdown of WinProc. |
- if (proc_info.hProcess) { |
- if (::PostThreadMessageW(proc_info.dwThreadId, WM_QUIT, 0, 0)) { |
- ::WaitForSingleObject(winproc_event, event_timeout); |
- } else { |
- // Ensure no strays. |
- ::TerminateProcess(proc_info.hProcess, 0); |
- ADD_FAILURE(); |
- } |
- EXPECT_TRUE(::CloseHandle(proc_info.hThread)); |
- EXPECT_TRUE(::CloseHandle(proc_info.hProcess)); |
- } |
- |
- // 5. Reg Restore |
- EXPECT_EQ(ERROR_SUCCESS, |
- app_init_key.WriteValue(enabled_value_name, orig_enabled_value)); |
- if (app_init_key.HasValue(signing_value_name)) |
- EXPECT_EQ(ERROR_SUCCESS, |
- app_init_key.WriteValue(signing_value_name, orig_signing_value)); |
- EXPECT_EQ(ERROR_SUCCESS, |
- app_init_key.WriteValue(dlls_value_name, orig_dlls.c_str())); |
-} |
- |
-void TestWin10ImageLoadRemote(bool is_success_test) { |
- // ***Insert a manual testing share UNC path here! |
- // E.g.: \\\\hostname\\sharename\\calc.exe |
- std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\""; |
- |
- sandbox::TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- // Set a policy that would normally allow for process creation. |
- policy->SetJobLevel(sandbox::JOB_NONE, 0); |
- policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED); |
- runner.SetDisableCsrss(false); |
- |
- if (!is_success_test) { |
- // Enable the NoRemote mitigation. |
- EXPECT_EQ(policy->SetDelayedProcessMitigations( |
- sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE), |
- sandbox::SBOX_ALL_OK); |
- } |
- |
- std::wstring test = L"TestChildProcess "; |
- test += unc.c_str(); |
- EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED |
- : sandbox::SBOX_TEST_FAILED), |
- runner.RunTest(test.c_str())); |
-} |
- |
-bool CheckWin10ImageLoadNoLowLabelPolicy() { |
- PROCESS_MITIGATION_IMAGE_LOAD_POLICY policy = {}; |
- if (!get_process_mitigation_policy(::GetCurrentProcess(), |
- ProcessImageLoadPolicy, &policy, |
- sizeof(policy))) { |
- return false; |
- } |
- return policy.NoLowMandatoryLabelImages; |
-} |
- |
-void TestWin10ImageLoadLowLabel(bool is_success_test) { |
- // Setup a mandatory low executable for this test (calc.exe). |
- // If anything fails during setup, ASSERT to end test. |
- base::FilePath orig_path; |
- ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &orig_path)); |
- orig_path = orig_path.Append(L"calc.exe"); |
- |
- base::ScopedTempDir temp_dir; |
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
- base::FilePath new_path = temp_dir.GetPath(); |
- new_path = new_path.Append(L"lowIL_calc.exe"); |
- |
- // Test file will be cleaned up by the ScopedTempDir. |
- ASSERT_TRUE(base::CopyFileW(orig_path, new_path)); |
- |
- std::wstring cmd_line = L"icacls \""; |
- cmd_line += new_path.value().c_str(); |
- cmd_line += L"\" /setintegritylevel Low"; |
- |
- base::LaunchOptions options = base::LaunchOptionsForTest(); |
- base::Process setup_proc = base::LaunchProcess(cmd_line.c_str(), options); |
- ASSERT_TRUE(setup_proc.IsValid()); |
- |
- int exit_code = 1; |
- if (!setup_proc.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(10), |
- &exit_code)) { |
- // Might have timed out, or might have failed. |
- // Terminate to make sure we clean up any mess. |
- setup_proc.Terminate(0, false); |
- ASSERT_TRUE(false); |
- } |
- // Make sure icacls was successful. |
- ASSERT_EQ(0, exit_code); |
- |
- sandbox::TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- // Set a policy that would normally allow for process creation. |
- policy->SetJobLevel(sandbox::JOB_NONE, 0); |
- policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED); |
- runner.SetDisableCsrss(false); |
- |
- if (!is_success_test) { |
- // Enable the NoLowLabel mitigation. |
- EXPECT_EQ(policy->SetDelayedProcessMitigations( |
- sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL), |
- sandbox::SBOX_ALL_OK); |
- } |
- |
- std::wstring test = L"TestChildProcess "; |
- test += new_path.value().c_str(); |
- |
- EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED |
- : sandbox::SBOX_TEST_FAILED), |
- runner.RunTest(test.c_str())); |
-} |
- |
-BOOL CALLBACK MonitorEnumCallback(HMONITOR monitor, |
- HDC hdc_monitor, |
- LPRECT rect_monitor, |
- LPARAM data) { |
- std::map<HMONITOR, base::string16>& monitors = |
- *reinterpret_cast<std::map<HMONITOR, base::string16>*>(data); |
- MONITORINFOEXW monitor_info = {}; |
- monitor_info.cbSize = sizeof(monitor_info); |
- |
- if (!::GetMonitorInfoW(monitor, |
- reinterpret_cast<MONITORINFO*>(&monitor_info))) |
- return FALSE; |
- monitors[monitor] = monitor_info.szDevice; |
- return TRUE; |
-} |
- |
-std::map<HMONITOR, std::wstring> EnumerateMonitors() { |
- std::map<HMONITOR, std::wstring> result; |
- ::EnumDisplayMonitors(nullptr, nullptr, MonitorEnumCallback, |
- reinterpret_cast<LPARAM>(&result)); |
- return result; |
-} |
- |
-#define HMONITOR_ENTRY(monitor) \ |
- result[reinterpret_cast<HMONITOR>(monitor)] = \ |
- base::StringPrintf(L"\\\\.\\DISPLAY%X", monitor) |
- |
-std::map<HMONITOR, std::wstring> GetTestMonitors() { |
- std::map<HMONITOR, std::wstring> result; |
- |
- HMONITOR_ENTRY(0x11111111); |
- HMONITOR_ENTRY(0x22222222); |
- HMONITOR_ENTRY(0x44444444); |
- HMONITOR_ENTRY(0x88888888); |
- return result; |
-} |
- |
-std::wstring UnicodeStringToString(PUNICODE_STRING name) { |
- return std::wstring(name->Buffer, |
- name->Buffer + (name->Length / sizeof(name->Buffer[0]))); |
-} |
- |
-// Returns an index 1, 2, 4 or 8 depening on the device. 0 on error. |
-DWORD GetTestDeviceMonitorIndex(PUNICODE_STRING device_name) { |
- std::wstring name = UnicodeStringToString(device_name); |
- std::map<HMONITOR, std::wstring> monitors = GetTestMonitors(); |
- for (const auto& monitor : monitors) { |
- if (name == monitor.second) |
- return static_cast<DWORD>(reinterpret_cast<uintptr_t>(monitor.first)) & |
- 0xF; |
- } |
- return 0; |
-} |
- |
-NTSTATUS WINAPI GetSuggestedOPMProtectedOutputArraySizeTest( |
- PUNICODE_STRING device_name, |
- DWORD* suggested_output_array_size) { |
- DWORD monitor = GetTestDeviceMonitorIndex(device_name); |
- if (!monitor) |
- return STATUS_OBJECT_NAME_NOT_FOUND; |
- *suggested_output_array_size = monitor; |
- return STATUS_SUCCESS; |
-} |
- |
-NTSTATUS WINAPI |
-CreateOPMProtectedOutputsTest(PUNICODE_STRING device_name, |
- DXGKMDT_OPM_VIDEO_OUTPUT_SEMANTICS vos, |
- DWORD output_array_size, |
- DWORD* num_in_output_array, |
- OPM_PROTECTED_OUTPUT_HANDLE* output_array) { |
- DWORD monitor = GetTestDeviceMonitorIndex(device_name); |
- if (!monitor) |
- return STATUS_OBJECT_NAME_NOT_FOUND; |
- if (vos != DXGKMDT_OPM_VOS_OPM_SEMANTICS) |
- return STATUS_INVALID_PARAMETER; |
- if (output_array_size != monitor) |
- return STATUS_INVALID_PARAMETER; |
- *num_in_output_array = monitor - 1; |
- for (DWORD index = 0; index < monitor - 1; ++index) { |
- output_array[index] = |
- reinterpret_cast<OPM_PROTECTED_OUTPUT_HANDLE>((monitor << 4) + index); |
- } |
- return STATUS_SUCCESS; |
-} |
- |
-ULONG CalculateCertLength(ULONG monitor) { |
- return (monitor * 0x800) + 0xabc; |
-} |
- |
-NTSTATUS WINAPI GetCertificateTest(PUNICODE_STRING device_name, |
- DXGKMDT_CERTIFICATE_TYPE certificate_type, |
- BYTE* certificate, |
- ULONG certificate_length) { |
- DWORD monitor = GetTestDeviceMonitorIndex(device_name); |
- if (!monitor) |
- return STATUS_OBJECT_NAME_NOT_FOUND; |
- if (certificate_type != DXGKMDT_OPM_CERTIFICATE) |
- return STATUS_INVALID_PARAMETER; |
- if (certificate_length != CalculateCertLength(monitor)) |
- return STATUS_INVALID_PARAMETER; |
- memset(certificate, 'A' + monitor, certificate_length); |
- return STATUS_SUCCESS; |
-} |
- |
-NTSTATUS WINAPI |
-GetCertificateSizeTest(PUNICODE_STRING device_name, |
- DXGKMDT_CERTIFICATE_TYPE certificate_type, |
- ULONG* certificate_length) { |
- DWORD monitor = GetTestDeviceMonitorIndex(device_name); |
- if (!monitor) |
- return STATUS_OBJECT_NAME_NOT_FOUND; |
- if (certificate_type != DXGKMDT_OPM_CERTIFICATE) |
- return STATUS_INVALID_PARAMETER; |
- *certificate_length = CalculateCertLength(monitor); |
- return STATUS_SUCCESS; |
-} |
- |
-// Check for valid output handle and return the monitor index. |
-DWORD IsValidProtectedOutput(OPM_PROTECTED_OUTPUT_HANDLE protected_output) { |
- uintptr_t handle = reinterpret_cast<uintptr_t>(protected_output); |
- uintptr_t monitor = handle >> 4; |
- uintptr_t index = handle & 0xF; |
- switch (monitor) { |
- case 1: |
- case 2: |
- case 4: |
- case 8: |
- break; |
- default: |
- return 0; |
- } |
- if (index >= (monitor - 1)) |
- return 0; |
- return static_cast<DWORD>(monitor); |
-} |
- |
-NTSTATUS WINAPI |
-GetCertificateByHandleTest(OPM_PROTECTED_OUTPUT_HANDLE protected_output, |
- DXGKMDT_CERTIFICATE_TYPE certificate_type, |
- BYTE* certificate, |
- ULONG certificate_length) { |
- DWORD monitor = IsValidProtectedOutput(protected_output); |
- if (!monitor) |
- return STATUS_INVALID_HANDLE; |
- if (certificate_type != DXGKMDT_OPM_CERTIFICATE) |
- return STATUS_INVALID_PARAMETER; |
- if (certificate_length != CalculateCertLength(monitor)) |
- return STATUS_INVALID_PARAMETER; |
- memset(certificate, 'A' + monitor, certificate_length); |
- return STATUS_SUCCESS; |
-} |
- |
-NTSTATUS WINAPI |
-GetCertificateSizeByHandleTest(OPM_PROTECTED_OUTPUT_HANDLE protected_output, |
- DXGKMDT_CERTIFICATE_TYPE certificate_type, |
- ULONG* certificate_length) { |
- DWORD monitor = IsValidProtectedOutput(protected_output); |
- if (!monitor) |
- return STATUS_INVALID_HANDLE; |
- if (certificate_type != DXGKMDT_OPM_CERTIFICATE) |
- return STATUS_INVALID_PARAMETER; |
- *certificate_length = CalculateCertLength(monitor); |
- return STATUS_SUCCESS; |
-} |
- |
-NTSTATUS WINAPI |
-DestroyOPMProtectedOutputTest(OPM_PROTECTED_OUTPUT_HANDLE protected_output) { |
- if (!IsValidProtectedOutput(protected_output)) |
- return STATUS_INVALID_HANDLE; |
- return STATUS_SUCCESS; |
-} |
- |
-NTSTATUS WINAPI ConfigureOPMProtectedOutputTest( |
- OPM_PROTECTED_OUTPUT_HANDLE protected_output, |
- const DXGKMDT_OPM_CONFIGURE_PARAMETERS* parameters, |
- ULONG additional_parameters_size, |
- const BYTE* additional_parameters) { |
- if (!IsValidProtectedOutput(protected_output)) |
- return STATUS_INVALID_HANDLE; |
- if (additional_parameters && additional_parameters_size) |
- return STATUS_INVALID_PARAMETER; |
- return STATUS_SUCCESS; |
-} |
- |
-NTSTATUS WINAPI GetOPMInformationTest( |
- OPM_PROTECTED_OUTPUT_HANDLE protected_output, |
- const DXGKMDT_OPM_GET_INFO_PARAMETERS* parameters, |
- DXGKMDT_OPM_REQUESTED_INFORMATION* requested_information) { |
- DWORD monitor = IsValidProtectedOutput(protected_output); |
- if (!monitor) |
- return STATUS_INVALID_HANDLE; |
- memset(requested_information, '0' + monitor, |
- sizeof(DXGKMDT_OPM_REQUESTED_INFORMATION)); |
- return STATUS_SUCCESS; |
-} |
- |
-NTSTATUS WINAPI |
-GetOPMRandomNumberTest(OPM_PROTECTED_OUTPUT_HANDLE protected_output, |
- DXGKMDT_OPM_RANDOM_NUMBER* random_number) { |
- DWORD monitor = IsValidProtectedOutput(protected_output); |
- if (!monitor) |
- return STATUS_INVALID_HANDLE; |
- memset(random_number->abRandomNumber, '!' + monitor, |
- sizeof(random_number->abRandomNumber)); |
- return STATUS_SUCCESS; |
-} |
- |
-NTSTATUS WINAPI SetOPMSigningKeyAndSequenceNumbersTest( |
- OPM_PROTECTED_OUTPUT_HANDLE protected_output, |
- const DXGKMDT_OPM_ENCRYPTED_PARAMETERS* parameters) { |
- DWORD monitor = IsValidProtectedOutput(protected_output); |
- if (!monitor) |
- return STATUS_INVALID_HANDLE; |
- DXGKMDT_OPM_ENCRYPTED_PARAMETERS test_params = {}; |
- memset(test_params.abEncryptedParameters, 'a' + monitor, |
- sizeof(test_params.abEncryptedParameters)); |
- if (memcmp(test_params.abEncryptedParameters, |
- parameters->abEncryptedParameters, |
- sizeof(test_params.abEncryptedParameters)) != 0) |
- return STATUS_INVALID_PARAMETER; |
- return STATUS_SUCCESS; |
-} |
- |
-BOOL WINAPI EnumDisplayMonitorsTest(HDC hdc, |
- LPCRECT clip_rect, |
- MONITORENUMPROC enum_function, |
- LPARAM data) { |
- RECT rc = {}; |
- for (const auto& monitor : GetTestMonitors()) { |
- if (!enum_function(monitor.first, hdc, &rc, data)) |
- return FALSE; |
- } |
- return TRUE; |
-} |
- |
-BOOL WINAPI GetMonitorInfoWTest(HMONITOR monitor, LPMONITORINFO monitor_info) { |
- std::map<HMONITOR, std::wstring> monitors = GetTestMonitors(); |
- if (monitor_info->cbSize != sizeof(MONITORINFO) && |
- monitor_info->cbSize != sizeof(MONITORINFOEXW)) |
- return FALSE; |
- auto it = monitors.find(monitor); |
- if (it == monitors.end()) |
- return FALSE; |
- if (monitor_info->cbSize == sizeof(MONITORINFOEXW)) { |
- MONITORINFOEXW* monitor_info_ex = |
- reinterpret_cast<MONITORINFOEXW*>(monitor_info); |
- size_t copy_size = (it->second.size() + 1) * sizeof(WCHAR); |
- if (copy_size > sizeof(monitor_info_ex->szDevice) - sizeof(WCHAR)) |
- copy_size = sizeof(monitor_info_ex->szDevice) - sizeof(WCHAR); |
- memset(monitor_info_ex->szDevice, 0, sizeof(monitor_info_ex->szDevice)); |
- memcpy(monitor_info_ex->szDevice, it->second.c_str(), copy_size); |
- } |
- return TRUE; |
-} |
- |
-#define RETURN_TEST_FUNC(n) \ |
- if (strcmp(name, #n) == 0) { \ |
- return n##Test; \ |
- } |
- |
-void* FunctionOverrideForTest(const char* name) { |
- RETURN_TEST_FUNC(GetSuggestedOPMProtectedOutputArraySize); |
- RETURN_TEST_FUNC(CreateOPMProtectedOutputs); |
- RETURN_TEST_FUNC(GetCertificate); |
- RETURN_TEST_FUNC(GetCertificateSize); |
- RETURN_TEST_FUNC(DestroyOPMProtectedOutput); |
- RETURN_TEST_FUNC(ConfigureOPMProtectedOutput); |
- RETURN_TEST_FUNC(GetOPMInformation); |
- RETURN_TEST_FUNC(GetOPMRandomNumber); |
- RETURN_TEST_FUNC(SetOPMSigningKeyAndSequenceNumbers); |
- RETURN_TEST_FUNC(EnumDisplayMonitors); |
- RETURN_TEST_FUNC(GetMonitorInfoW); |
- RETURN_TEST_FUNC(GetCertificateByHandle); |
- RETURN_TEST_FUNC(GetCertificateSizeByHandle); |
- NOTREACHED(); |
- return nullptr; |
-} |
- |
-} // namespace |
- |
-namespace sandbox { |
- |
-// A shared helper test command that will attempt to CreateProcess with a given |
-// command line. The second optional parameter will cause the child process to |
-// return that as an exit code on termination. |
-// |
-// ***Make sure you've enabled basic process creation in the |
-// test sandbox settings via: |
-// sandbox::TargetPolicy::SetJobLevel(), |
-// sandbox::TargetPolicy::SetTokenLevel(), |
-// and TestRunner::SetDisableCsrss(). |
-SBOX_TESTS_COMMAND int TestChildProcess(int argc, wchar_t** argv) { |
- if (argc < 1) |
- return SBOX_TEST_INVALID_PARAMETER; |
- |
- int desired_exit_code = 0; |
- |
- if (argc == 2) { |
- desired_exit_code = wcstoul(argv[1], nullptr, 0); |
- } |
- |
- std::wstring cmd = argv[0]; |
- base::LaunchOptions options = base::LaunchOptionsForTest(); |
- base::Process setup_proc = base::LaunchProcess(cmd.c_str(), options); |
- |
- if (setup_proc.IsValid()) { |
- setup_proc.Terminate(desired_exit_code, false); |
- return SBOX_TEST_SUCCEEDED; |
- } |
- // Note: GetLastError from CreateProcess returns 5, "ERROR_ACCESS_DENIED". |
- return SBOX_TEST_FAILED; |
-} |
- |
-//------------------------------------------------------------------------------ |
-// Win8 Checks: |
-// MITIGATION_DEP(_NO_ATL_THUNK) |
-// MITIGATION_RELOCATE_IMAGE(_REQUIRED) - ASLR |
-// MITIGATION_STRICT_HANDLE_CHECKS |
-// >= Win8 |
-//------------------------------------------------------------------------------ |
- |
-SBOX_TESTS_COMMAND int CheckWin8(int argc, wchar_t** argv) { |
- get_process_mitigation_policy = |
- reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
- ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
- if (!get_process_mitigation_policy) |
- return SBOX_TEST_NOT_FOUND; |
- |
-#if !defined(_WIN64) // DEP is always enabled on 64-bit. |
- if (!CheckWin8DepPolicy()) |
- return SBOX_TEST_FIRST_ERROR; |
-#endif |
- |
- if (!CheckWin8AslrPolicy()) |
- return SBOX_TEST_SECOND_ERROR; |
- |
- if (!CheckWin8StrictHandlePolicy()) |
- return SBOX_TEST_THIRD_ERROR; |
- |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-TEST(ProcessMitigationsTest, CheckWin8) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- // ASLR cannot be forced on start in debug builds. |
- constexpr sandbox::MitigationFlags kDebugDelayedMitigations = |
- MITIGATION_RELOCATE_IMAGE | MITIGATION_RELOCATE_IMAGE_REQUIRED; |
- |
- sandbox::MitigationFlags mitigations = |
- MITIGATION_DEP | MITIGATION_DEP_NO_ATL_THUNK; |
-#if defined(NDEBUG) |
- mitigations |= kDebugDelayedMitigations; |
-#endif |
- |
- EXPECT_EQ(policy->SetProcessMitigations(mitigations), SBOX_ALL_OK); |
- |
- mitigations |= MITIGATION_STRICT_HANDLE_CHECKS; |
- |
-#if !defined(NDEBUG) |
- mitigations |= kDebugDelayedMitigations; |
-#endif |
- |
- EXPECT_EQ(policy->SetDelayedProcessMitigations(mitigations), SBOX_ALL_OK); |
- |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8")); |
-} |
- |
-//------------------------------------------------------------------------------ |
-// DEP (MITIGATION_DEP) |
-// < Win8 x86 |
-//------------------------------------------------------------------------------ |
- |
-SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t** argv) { |
- GetProcessDEPPolicyFunction get_process_dep_policy = |
- reinterpret_cast<GetProcessDEPPolicyFunction>(::GetProcAddress( |
- ::GetModuleHandleW(L"kernel32.dll"), "GetProcessDEPPolicy")); |
- if (get_process_dep_policy) { |
- BOOL is_permanent = FALSE; |
- DWORD dep_flags = 0; |
- |
- if (!get_process_dep_policy(::GetCurrentProcess(), &dep_flags, |
- &is_permanent)) { |
- return SBOX_TEST_FIRST_ERROR; |
- } |
- |
- if (!(dep_flags & PROCESS_DEP_ENABLE) || !is_permanent) |
- return SBOX_TEST_SECOND_ERROR; |
- |
- } else { |
- NtQueryInformationProcessFunction query_information_process = NULL; |
- ResolveNTFunctionPtr("NtQueryInformationProcess", |
- &query_information_process); |
- if (!query_information_process) |
- return SBOX_TEST_NOT_FOUND; |
- |
- ULONG size = 0; |
- ULONG dep_flags = 0; |
- if (!SUCCEEDED(query_information_process(::GetCurrentProcess(), |
- ProcessExecuteFlags, &dep_flags, |
- sizeof(dep_flags), &size))) { |
- return SBOX_TEST_THIRD_ERROR; |
- } |
- |
- static const int MEM_EXECUTE_OPTION_DISABLE = 2; |
- static const int MEM_EXECUTE_OPTION_PERMANENT = 8; |
- dep_flags &= 0xff; |
- |
- if (dep_flags != |
- (MEM_EXECUTE_OPTION_DISABLE | MEM_EXECUTE_OPTION_PERMANENT)) { |
- return SBOX_TEST_FOURTH_ERROR; |
- } |
- } |
- |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-#if !defined(_WIN64) // DEP is always enabled on 64-bit. |
-TEST(ProcessMitigationsTest, CheckDep) { |
- if (base::win::GetVersion() >= base::win::VERSION_WIN8) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_DEP | |
- MITIGATION_DEP_NO_ATL_THUNK | |
- MITIGATION_SEHOP), |
- SBOX_ALL_OK); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckDep")); |
-} |
-#endif |
- |
-//------------------------------------------------------------------------------ |
-// Win32k Lockdown (MITIGATION_WIN32K_DISABLE) |
-// >= Win8 |
-//------------------------------------------------------------------------------ |
- |
-SBOX_TESTS_COMMAND int CheckWin8Lockdown(int argc, wchar_t** argv) { |
- get_process_mitigation_policy = |
- reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
- ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
- if (!get_process_mitigation_policy) |
- return SBOX_TEST_NOT_FOUND; |
- |
- if (!CheckWin8Win32CallPolicy()) |
- return SBOX_TEST_FIRST_ERROR; |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-SBOX_TESTS_COMMAND int CheckWin8MonitorsRedirection(int argc, wchar_t** argv) { |
- std::map<HMONITOR, base::string16> monitors = EnumerateMonitors(); |
- std::map<HMONITOR, base::string16> monitors_to_test = GetTestMonitors(); |
- if (monitors.size() != monitors_to_test.size()) |
- return SBOX_TEST_FIRST_ERROR; |
- |
- for (const auto& monitor : monitors) { |
- auto result = monitors_to_test.find(monitor.first); |
- if (result == monitors_to_test.end()) |
- return SBOX_TEST_SECOND_ERROR; |
- if (result->second != monitor.second) |
- return SBOX_TEST_THIRD_ERROR; |
- } |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-SBOX_TESTS_COMMAND int CheckWin8MonitorInfo(int argc, wchar_t** argv) { |
- std::map<HMONITOR, base::string16> monitors_to_test = GetTestMonitors(); |
- MONITORINFO monitor_info = {}; |
- MONITORINFOEXW monitor_info_exw = {}; |
- MONITORINFOEXA monitor_info_exa = {}; |
- HMONITOR valid_monitor = monitors_to_test.begin()->first; |
- std::wstring valid_device = monitors_to_test.begin()->second; |
- monitor_info.cbSize = sizeof(MONITORINFO); |
- if (!::GetMonitorInfoW(valid_monitor, &monitor_info)) |
- return SBOX_TEST_FIRST_ERROR; |
- monitor_info.cbSize = sizeof(MONITORINFO); |
- if (!::GetMonitorInfoA(valid_monitor, &monitor_info)) |
- return SBOX_TEST_SECOND_ERROR; |
- monitor_info_exw.cbSize = sizeof(MONITORINFOEXW); |
- if (!::GetMonitorInfoW(valid_monitor, |
- reinterpret_cast<MONITORINFO*>(&monitor_info_exw)) || |
- valid_device != monitor_info_exw.szDevice) { |
- return SBOX_TEST_THIRD_ERROR; |
- } |
- monitor_info_exa.cbSize = sizeof(MONITORINFOEXA); |
- if (!::GetMonitorInfoA(valid_monitor, |
- reinterpret_cast<MONITORINFO*>(&monitor_info_exa)) || |
- valid_device != base::ASCIIToUTF16(monitor_info_exa.szDevice)) { |
- return SBOX_TEST_FOURTH_ERROR; |
- } |
- |
- // Invalid size checks. |
- monitor_info.cbSize = 0; |
- if (::GetMonitorInfoW(valid_monitor, &monitor_info)) |
- return SBOX_TEST_FIFTH_ERROR; |
- monitor_info.cbSize = 0x10000; |
- if (::GetMonitorInfoW(valid_monitor, &monitor_info)) |
- return SBOX_TEST_SIXTH_ERROR; |
- |
- // Check that an invalid handle isn't accepted. |
- HMONITOR invalid_monitor = reinterpret_cast<HMONITOR>(-1); |
- monitor_info.cbSize = sizeof(MONITORINFO); |
- if (::GetMonitorInfoW(invalid_monitor, &monitor_info)) |
- return SBOX_TEST_SEVENTH_ERROR; |
- |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-bool RunTestsOnVideoOutputConfigure(uintptr_t monitor_index, |
- IOPMVideoOutput* video_output) { |
- OPM_CONFIGURE_PARAMETERS config_params = {}; |
- OPM_SET_PROTECTION_LEVEL_PARAMETERS* protection_level = |
- reinterpret_cast<OPM_SET_PROTECTION_LEVEL_PARAMETERS*>( |
- config_params.abParameters); |
- protection_level->ulProtectionType = OPM_PROTECTION_TYPE_HDCP; |
- protection_level->ulProtectionLevel = OPM_HDCP_ON; |
- config_params.guidSetting = OPM_SET_PROTECTION_LEVEL; |
- config_params.cbParametersSize = sizeof(OPM_SET_PROTECTION_LEVEL_PARAMETERS); |
- HRESULT hr = video_output->Configure(&config_params, 0, nullptr); |
- if (FAILED(hr)) |
- return false; |
- protection_level->ulProtectionType = OPM_PROTECTION_TYPE_DPCP; |
- hr = video_output->Configure(&config_params, 0, nullptr); |
- if (FAILED(hr)) |
- return false; |
- protection_level->ulProtectionLevel = OPM_HDCP_OFF; |
- hr = video_output->Configure(&config_params, 0, nullptr); |
- if (FAILED(hr)) |
- return false; |
- BYTE dummy_byte = 0; |
- hr = video_output->Configure(&config_params, 1, &dummy_byte); |
- if (SUCCEEDED(hr)) |
- return false; |
- protection_level->ulProtectionType = 0xFFFFFFFF; |
- hr = video_output->Configure(&config_params, 0, nullptr); |
- if (SUCCEEDED(hr)) |
- return false; |
- // Invalid protection level test. |
- protection_level->ulProtectionType = OPM_PROTECTION_TYPE_HDCP; |
- protection_level->ulProtectionLevel = OPM_HDCP_ON + 1; |
- hr = video_output->Configure(&config_params, 0, nullptr); |
- if (SUCCEEDED(hr)) |
- return false; |
- hr = video_output->Configure(&config_params, 0, nullptr); |
- if (SUCCEEDED(hr)) |
- return false; |
- config_params.guidSetting = OPM_SET_HDCP_SRM; |
- OPM_SET_HDCP_SRM_PARAMETERS* srm_parameters = |
- reinterpret_cast<OPM_SET_HDCP_SRM_PARAMETERS*>( |
- config_params.abParameters); |
- srm_parameters->ulSRMVersion = 1; |
- config_params.cbParametersSize = sizeof(OPM_SET_HDCP_SRM_PARAMETERS); |
- hr = video_output->Configure(&config_params, 0, nullptr); |
- if (SUCCEEDED(hr)) |
- return false; |
- return true; |
-} |
- |
-bool RunTestsOnVideoOutputFinishInitialization(uintptr_t monitor_index, |
- IOPMVideoOutput* video_output) { |
- OPM_ENCRYPTED_INITIALIZATION_PARAMETERS init_params = {}; |
- memset(init_params.abEncryptedInitializationParameters, 'a' + monitor_index, |
- sizeof(init_params.abEncryptedInitializationParameters)); |
- HRESULT hr = video_output->FinishInitialization(&init_params); |
- if (FAILED(hr)) |
- return false; |
- memset(init_params.abEncryptedInitializationParameters, 'Z' + monitor_index, |
- sizeof(init_params.abEncryptedInitializationParameters)); |
- hr = video_output->FinishInitialization(&init_params); |
- if (SUCCEEDED(hr)) |
- return false; |
- return true; |
-} |
- |
-bool RunTestsOnVideoOutputStartInitialization(uintptr_t monitor_index, |
- IOPMVideoOutput* video_output) { |
- OPM_RANDOM_NUMBER random_number = {}; |
- BYTE* certificate = nullptr; |
- ULONG certificate_length = 0; |
- |
- HRESULT hr = video_output->StartInitialization(&random_number, &certificate, |
- &certificate_length); |
- if (FAILED(hr)) |
- return false; |
- |
- if (certificate_length != CalculateCertLength(monitor_index)) |
- return false; |
- |
- for (ULONG i = 0; i < certificate_length; ++i) { |
- if (certificate[i] != 'A' + monitor_index) |
- return false; |
- } |
- |
- for (ULONG i = 0; i < sizeof(random_number.abRandomNumber); ++i) { |
- if (random_number.abRandomNumber[i] != '!' + monitor_index) |
- return false; |
- } |
- |
- return true; |
-} |
- |
-static bool SendSingleGetInfoRequest(uintptr_t monitor_index, |
- IOPMVideoOutput* video_output, |
- const GUID& request, |
- ULONG data_length, |
- void* data) { |
- OPM_GET_INFO_PARAMETERS params = {}; |
- OPM_REQUESTED_INFORMATION requested_information = {}; |
- BYTE* requested_information_ptr = |
- reinterpret_cast<BYTE*>(&requested_information); |
- params.guidInformation = request; |
- params.cbParametersSize = data_length; |
- memcpy(params.abParameters, data, data_length); |
- HRESULT hr = video_output->GetInformation(¶ms, &requested_information); |
- if (FAILED(hr)) |
- return false; |
- for (size_t i = 0; i < sizeof(OPM_REQUESTED_INFORMATION); ++i) { |
- if (requested_information_ptr[i] != '0' + monitor_index) |
- return false; |
- } |
- return true; |
-} |
- |
-bool RunTestsOnVideoOutputGetInformation(uintptr_t monitor_index, |
- IOPMVideoOutput* video_output) { |
- ULONG dummy = 0; |
- if (!SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_CONNECTOR_TYPE, 0, nullptr)) { |
- return false; |
- } |
- if (!SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_SUPPORTED_PROTECTION_TYPES, 0, |
- nullptr)) { |
- return false; |
- } |
- // These should fail due to invalid parameter sizes. |
- if (SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_CONNECTOR_TYPE, sizeof(dummy), &dummy)) { |
- return false; |
- } |
- if (SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_SUPPORTED_PROTECTION_TYPES, |
- sizeof(dummy), &dummy)) { |
- return false; |
- } |
- ULONG protection_type = OPM_PROTECTION_TYPE_HDCP; |
- if (!SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_ACTUAL_PROTECTION_LEVEL, |
- sizeof(protection_type), &protection_type)) { |
- return false; |
- } |
- protection_type = OPM_PROTECTION_TYPE_DPCP; |
- if (!SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_ACTUAL_PROTECTION_LEVEL, |
- sizeof(protection_type), &protection_type)) { |
- return false; |
- } |
- // These should fail as unsupported or invalid parameters. |
- protection_type = OPM_PROTECTION_TYPE_ACP; |
- if (SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_ACTUAL_PROTECTION_LEVEL, |
- sizeof(protection_type), &protection_type)) { |
- return false; |
- } |
- if (SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_ACTUAL_PROTECTION_LEVEL, 0, nullptr)) { |
- return false; |
- } |
- protection_type = OPM_PROTECTION_TYPE_HDCP; |
- if (!SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_VIRTUAL_PROTECTION_LEVEL, |
- sizeof(protection_type), &protection_type)) { |
- return false; |
- } |
- protection_type = OPM_PROTECTION_TYPE_DPCP; |
- if (!SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_VIRTUAL_PROTECTION_LEVEL, |
- sizeof(protection_type), &protection_type)) { |
- return false; |
- } |
- // These should fail as unsupported or invalid parameters. |
- protection_type = OPM_PROTECTION_TYPE_ACP; |
- if (SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_VIRTUAL_PROTECTION_LEVEL, |
- sizeof(protection_type), &protection_type)) { |
- return false; |
- } |
- if (SendSingleGetInfoRequest(monitor_index, video_output, |
- OPM_GET_VIRTUAL_PROTECTION_LEVEL, 0, nullptr)) { |
- return false; |
- } |
- // This should fail with unsupported request. |
- if (SendSingleGetInfoRequest(monitor_index, video_output, OPM_GET_CODEC_INFO, |
- 0, nullptr)) { |
- return false; |
- } |
- return true; |
-} |
- |
-int RunTestsOnVideoOutput(uintptr_t monitor_index, |
- IOPMVideoOutput* video_output) { |
- if (!RunTestsOnVideoOutputStartInitialization(monitor_index, video_output)) |
- return SBOX_TEST_FIRST_ERROR; |
- |
- if (!RunTestsOnVideoOutputFinishInitialization(monitor_index, video_output)) |
- return SBOX_TEST_SECOND_ERROR; |
- |
- if (!RunTestsOnVideoOutputConfigure(monitor_index, video_output)) |
- return SBOX_TEST_THIRD_ERROR; |
- |
- if (!RunTestsOnVideoOutputGetInformation(monitor_index, video_output)) |
- return SBOX_TEST_FOURTH_ERROR; |
- |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-SBOX_TESTS_COMMAND int CheckWin8OPMApis(int argc, wchar_t** argv) { |
- std::map<HMONITOR, base::string16> monitors = GetTestMonitors(); |
- for (const auto& monitor : monitors) { |
- ULONG output_count = 0; |
- IOPMVideoOutput** outputs = nullptr; |
- uintptr_t monitor_index = reinterpret_cast<uintptr_t>(monitor.first) & 0xF; |
- HRESULT hr = OPMGetVideoOutputsFromHMONITOR( |
- monitor.first, OPM_VOS_OPM_SEMANTICS, &output_count, &outputs); |
- if (monitor_index > 4) { |
- // These should fail because the certificate is too large. |
- if (SUCCEEDED(hr)) |
- return SBOX_TEST_FIRST_ERROR; |
- continue; |
- } |
- if (FAILED(hr)) |
- return SBOX_TEST_SECOND_ERROR; |
- if (output_count != monitor_index - 1) |
- return SBOX_TEST_THIRD_ERROR; |
- for (ULONG output_index = 0; output_index < output_count; ++output_index) { |
- int result = RunTestsOnVideoOutput(monitor_index, outputs[output_index]); |
- outputs[output_index]->Release(); |
- if (result != SBOX_TEST_SUCCEEDED) |
- return result; |
- } |
- ::CoTaskMemFree(outputs); |
- } |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation on |
-// the target process causes the launch to fail in process initialization. |
-// The test process itself links against user32/gdi32. |
-TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownFailure) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), |
- SBOX_ALL_OK); |
- EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); |
-} |
- |
-// This test validates that setting the MITIGATION_WIN32K_DISABLE mitigation |
-// along with the policy to fake user32 and gdi32 initialization successfully |
-// launches the target process. |
-// The test process itself links against user32/gdi32. |
-TEST(ProcessMitigationsTest, CheckWin8Win32KLockDownSuccess) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- ProcessMitigationsWin32KLockdownPolicy::SetOverrideForTestCallback( |
- FunctionOverrideForTest); |
- |
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), |
- SBOX_ALL_OK); |
- EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, |
- sandbox::TargetPolicy::FAKE_USER_GDI_INIT, NULL), |
- sandbox::SBOX_ALL_OK); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); |
- EXPECT_NE(SBOX_TEST_SUCCEEDED, |
- runner.RunTest(L"CheckWin8MonitorsRedirection")); |
- EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8MonitorInfo")); |
- EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8OPMApis")); |
-} |
- |
-// This test validates the even though we're running under win32k lockdown |
-// we can use the IPC redirection to enumerate the list of monitors. |
-TEST(ProcessMitigationsTest, CheckWin8Win32KRedirection) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- ProcessMitigationsWin32KLockdownPolicy::SetOverrideForTestCallback( |
- FunctionOverrideForTest); |
- |
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE), |
- SBOX_ALL_OK); |
- EXPECT_EQ(policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN, |
- sandbox::TargetPolicy::IMPLEMENT_OPM_APIS, NULL), |
- sandbox::SBOX_ALL_OK); |
- policy->SetEnableOPMRedirection(); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8Lockdown")); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
- runner.RunTest(L"CheckWin8MonitorsRedirection")); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8MonitorInfo")); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin8OPMApis")); |
-} |
- |
-//------------------------------------------------------------------------------ |
-// Disable extension points (MITIGATION_EXTENSION_POINT_DISABLE). |
-// >= Win8 |
-//------------------------------------------------------------------------------ |
-SBOX_TESTS_COMMAND int CheckWin8ExtensionPointSetting(int argc, |
- wchar_t** argv) { |
- get_process_mitigation_policy = |
- reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
- ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
- if (!get_process_mitigation_policy) |
- return SBOX_TEST_NOT_FOUND; |
- |
- if (!CheckWin8ExtensionPointPolicy()) |
- return SBOX_TEST_FIRST_ERROR; |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE |
-// mitigation enables the setting on a process. |
-TEST(ProcessMitigationsTest, CheckWin8ExtensionPointPolicySuccess) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_EXTENSION_POINT_DISABLE), |
- SBOX_ALL_OK); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
- runner.RunTest(L"CheckWin8ExtensionPointSetting")); |
-} |
- |
-// This test validates that a "legitimate" global hook CAN be set on the |
-// sandboxed proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE |
-// mitigation is not set. |
-// |
-// MANUAL testing only. |
-TEST(ProcessMitigationsTest, |
- DISABLED_CheckWin8ExtensionPoint_GlobalHook_Success) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); |
- EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); |
- |
- // (is_success_test, global_hook) |
- TestWin8ExtensionPointHookWrapper(true, true); |
- |
- EXPECT_TRUE(::ReleaseMutex(mutex)); |
- EXPECT_TRUE(::CloseHandle(mutex)); |
-} |
- |
-// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE |
-// mitigation prevents a global hook on WinProc. |
-// |
-// MANUAL testing only. |
-TEST(ProcessMitigationsTest, |
- DISABLED_CheckWin8ExtensionPoint_GlobalHook_Failure) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); |
- EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); |
- |
- // (is_success_test, global_hook) |
- TestWin8ExtensionPointHookWrapper(false, true); |
- |
- EXPECT_TRUE(::ReleaseMutex(mutex)); |
- EXPECT_TRUE(::CloseHandle(mutex)); |
-} |
- |
-// This test validates that a "legitimate" hook CAN be set on the sandboxed |
-// proc/thread if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. |
-// |
-// MANUAL testing only. |
-TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Success) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); |
- EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); |
- |
- // (is_success_test, global_hook) |
- TestWin8ExtensionPointHookWrapper(true, false); |
- |
- EXPECT_TRUE(::ReleaseMutex(mutex)); |
- EXPECT_TRUE(::CloseHandle(mutex)); |
-} |
- |
-// *** Important: MITIGATION_EXTENSION_POINT_DISABLE does NOT prevent |
-// hooks targetted at a specific thread id. It only prevents |
-// global hooks. So this test does NOT actually expect the hook |
-// to fail (see TestWin8ExtensionPointHookWrapper function) even |
-// with the mitigation on. |
-// |
-// MANUAL testing only. |
-TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_Hook_Failure) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); |
- EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); |
- |
- // (is_success_test, global_hook) |
- TestWin8ExtensionPointHookWrapper(false, false); |
- |
- EXPECT_TRUE(::ReleaseMutex(mutex)); |
- EXPECT_TRUE(::CloseHandle(mutex)); |
-} |
- |
-// This test validates that an AppInit Dll CAN be added to a target |
-// WinProc if the MITIGATION_EXTENSION_POINT_DISABLE mitigation is not set. |
-// |
-// MANUAL testing only. |
-// Must run this test as admin/elevated. |
-TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Success) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); |
- EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); |
- |
- TestWin8ExtensionPointAppInitWrapper(true); |
- |
- EXPECT_TRUE(::ReleaseMutex(mutex)); |
- EXPECT_TRUE(::CloseHandle(mutex)); |
-} |
- |
-// This test validates that setting the MITIGATION_EXTENSION_POINT_DISABLE |
-// mitigation prevents the loading of any AppInit Dll into WinProc. |
-// |
-// MANUAL testing only. |
-// Must run this test as admin/elevated. |
-TEST(ProcessMitigationsTest, DISABLED_CheckWin8ExtensionPoint_AppInit_Failure) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN8) |
- return; |
- |
- HANDLE mutex = ::CreateMutexW(NULL, FALSE, g_extension_point_test_mutex); |
- EXPECT_TRUE(mutex != NULL && mutex != INVALID_HANDLE_VALUE); |
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex, event_timeout)); |
- |
- TestWin8ExtensionPointAppInitWrapper(false); |
- |
- EXPECT_TRUE(::ReleaseMutex(mutex)); |
- EXPECT_TRUE(::CloseHandle(mutex)); |
-} |
- |
-//------------------------------------------------------------------------------ |
-// Disable non-system font loads (MITIGATION_NONSYSTEM_FONT_DISABLE) |
-// >= Win10 |
-//------------------------------------------------------------------------------ |
- |
-SBOX_TESTS_COMMAND int CheckWin10FontLockDown(int argc, wchar_t** argv) { |
- get_process_mitigation_policy = |
- reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
- ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
- if (!get_process_mitigation_policy) |
- return SBOX_TEST_NOT_FOUND; |
- |
- if (!CheckWin10FontPolicy()) |
- return SBOX_TEST_FIRST_ERROR; |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-SBOX_TESTS_COMMAND int CheckWin10FontLoad(int argc, wchar_t** argv) { |
- if (argc < 1) |
- return SBOX_TEST_INVALID_PARAMETER; |
- |
- HMODULE gdi_module = ::LoadLibraryW(L"gdi32.dll"); |
- if (!gdi_module) |
- return SBOX_TEST_NOT_FOUND; |
- |
- AddFontMemResourceExFunction add_font_mem_resource = |
- reinterpret_cast<AddFontMemResourceExFunction>( |
- ::GetProcAddress(gdi_module, "AddFontMemResourceEx")); |
- |
- RemoveFontMemResourceExFunction rem_font_mem_resource = |
- reinterpret_cast<RemoveFontMemResourceExFunction>( |
- ::GetProcAddress(gdi_module, "RemoveFontMemResourceEx")); |
- |
- if (!add_font_mem_resource || !rem_font_mem_resource) |
- return SBOX_TEST_NOT_FOUND; |
- |
- // Open font file passed in as an argument. |
- base::File file(base::FilePath(argv[0]), |
- base::File::FLAG_OPEN | base::File::FLAG_READ); |
- if (!file.IsValid()) |
- // Failed to open the font file passed in. |
- return SBOX_TEST_NOT_FOUND; |
- |
- std::vector<char> font_data; |
- int64_t len = file.GetLength(); |
- if (len < 0) |
- return SBOX_TEST_NOT_FOUND; |
- font_data.resize(len); |
- |
- int read = file.Read(0, &font_data[0], len); |
- file.Close(); |
- |
- if (read != len) |
- return SBOX_TEST_NOT_FOUND; |
- |
- DWORD font_count = 0; |
- HANDLE font_handle = add_font_mem_resource( |
- &font_data[0], static_cast<DWORD>(font_data.size()), NULL, &font_count); |
- |
- if (font_handle) { |
- rem_font_mem_resource(font_handle); |
- return SBOX_TEST_SUCCEEDED; |
- } |
- |
- return SBOX_TEST_FAILED; |
-} |
- |
-// This test validates that setting the MITIGATION_NON_SYSTEM_FONTS_DISABLE |
-// mitigation enables the setting on a process. |
-TEST(ProcessMitigationsTest, CheckWin10NonSystemFontLockDownPolicySuccess) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_NONSYSTEM_FONT_DISABLE), |
- SBOX_ALL_OK); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckWin10FontLockDown")); |
-} |
- |
-// This test validates that we can load a non-system font |
-// if the MITIGATION_NON_SYSTEM_FONTS_DISABLE |
-// mitigation is NOT set. |
-TEST(ProcessMitigationsTest, CheckWin10NonSystemFontLockDownLoadSuccess) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10) |
- return; |
- |
- base::FilePath font_path; |
- EXPECT_TRUE(base::PathService::Get(base::DIR_WINDOWS_FONTS, &font_path)); |
- // Arial font should always be available |
- font_path = font_path.Append(L"arial.ttf"); |
- |
- TestRunner runner; |
- EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, |
- font_path.value().c_str())); |
- |
- std::wstring test_command = L"CheckWin10FontLoad \""; |
- test_command += font_path.value().c_str(); |
- test_command += L"\""; |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str())); |
-} |
- |
-// This test validates that setting the MITIGATION_NON_SYSTEM_FONTS_DISABLE |
-// mitigation prevents the loading of a non-system font. |
-TEST(ProcessMitigationsTest, CheckWin10NonSystemFontLockDownLoadFailure) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10) |
- return; |
- |
- base::FilePath font_path; |
- EXPECT_TRUE(base::PathService::Get(base::DIR_WINDOWS_FONTS, &font_path)); |
- // Arial font should always be available |
- font_path = font_path.Append(L"arial.ttf"); |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, |
- font_path.value().c_str())); |
- |
- // Turn on the non-system font disable mitigation. |
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_NONSYSTEM_FONT_DISABLE), |
- SBOX_ALL_OK); |
- |
- std::wstring test_command = L"CheckWin10FontLoad \""; |
- test_command += font_path.value().c_str(); |
- test_command += L"\""; |
- |
- EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(test_command.c_str())); |
-} |
- |
-//------------------------------------------------------------------------------ |
-// Disable image load from remote devices (MITIGATION_IMAGE_LOAD_NO_REMOTE). |
-// >= Win10_TH2 |
-//------------------------------------------------------------------------------ |
- |
-SBOX_TESTS_COMMAND int CheckWin10ImageLoadNoRemote(int argc, wchar_t** argv) { |
- get_process_mitigation_policy = |
- reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
- ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
- if (!get_process_mitigation_policy) |
- return SBOX_TEST_NOT_FOUND; |
- |
- if (!CheckWin10ImageLoadNoRemotePolicy()) |
- return SBOX_TEST_FIRST_ERROR; |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE |
-// mitigation enables the setting on a process. |
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoRemotePolicySuccess) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- EXPECT_EQ( |
- policy->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE), |
- SBOX_ALL_OK); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
- runner.RunTest(L"CheckWin10ImageLoadNoRemote")); |
-} |
- |
-// This test validates that we CAN create a new process from |
-// a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE |
-// mitigation is NOT set. |
-// |
-// MANUAL testing only. |
-TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
- return; |
- |
- TestWin10ImageLoadRemote(true); |
-} |
- |
-// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE |
-// mitigation prevents creating a new process from a remote |
-// UNC device. |
-// |
-// MANUAL testing only. |
-TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
- return; |
- |
- TestWin10ImageLoadRemote(false); |
-} |
- |
-//------------------------------------------------------------------------------ |
-// Disable image load when "mandatory low label" (integrity level). |
-// (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL) |
-// >= Win10_TH2 |
-//------------------------------------------------------------------------------ |
- |
-SBOX_TESTS_COMMAND int CheckWin10ImageLoadNoLowLabel(int argc, wchar_t** argv) { |
- get_process_mitigation_policy = |
- reinterpret_cast<GetProcessMitigationPolicyFunction>(::GetProcAddress( |
- ::GetModuleHandleW(L"kernel32.dll"), "GetProcessMitigationPolicy")); |
- if (!get_process_mitigation_policy) |
- return SBOX_TEST_NOT_FOUND; |
- |
- if (!CheckWin10ImageLoadNoLowLabelPolicy()) |
- return SBOX_TEST_FIRST_ERROR; |
- return SBOX_TEST_SUCCEEDED; |
-} |
- |
-// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
-// mitigation enables the setting on a process. |
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelPolicySuccess) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
- return; |
- |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- EXPECT_EQ( |
- policy->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL), |
- SBOX_ALL_OK); |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, |
- runner.RunTest(L"CheckWin10ImageLoadNoLowLabel")); |
-} |
- |
-// This test validates that we CAN create a new process with |
-// low mandatory label (IL), if the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
-// mitigation is NOT set. |
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelSuccess) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
- return; |
- |
- TestWin10ImageLoadLowLabel(true); |
-} |
- |
-// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
-// mitigation prevents creating a new process with low mandatory label (IL). |
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelFailure) { |
- if (base::win::GetVersion() < base::win::VERSION_WIN10_TH2) |
- return; |
- |
- TestWin10ImageLoadLowLabel(false); |
-} |
- |
-//------------------------------------------------------------------------------ |
-// Disable child process creation. |
-// - JobLevel <= JOB_LIMITED_USER (on < WIN10_TH2). |
-// - JobLevel <= JOB_LIMITED_USER which also triggers setting |
-// PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY to |
-// PROCESS_CREATION_CHILD_PROCESS_RESTRICTED in |
-// BrokerServicesBase::SpawnTarget (on >= WIN10_TH2). |
-//------------------------------------------------------------------------------ |
- |
-// This test validates that we can spawn a child process if |
-// MITIGATION_CHILD_PROCESS_CREATION_RESTRICTED mitigation is |
-// not set. |
-TEST(ProcessMitigationsTest, CheckChildProcessSuccess) { |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- // Set a policy that would normally allow for process creation. |
- policy->SetJobLevel(JOB_INTERACTIVE, 0); |
- policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED); |
- runner.SetDisableCsrss(false); |
- |
- base::FilePath cmd; |
- EXPECT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &cmd)); |
- cmd = cmd.Append(L"calc.exe"); |
- |
- std::wstring test_command = L"TestChildProcess "; |
- test_command += cmd.value().c_str(); |
- |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str())); |
-} |
- |
-// This test validates that setting the |
-// MITIGATION_CHILD_PROCESS_CREATION_RESTRICTED mitigation prevents |
-// the spawning of child processes. |
-TEST(ProcessMitigationsTest, CheckChildProcessFailure) { |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- // Now set the job level to be <= JOB_LIMITED_USER |
- // and ensure we can no longer create a child process. |
- policy->SetJobLevel(JOB_LIMITED_USER, 0); |
- policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED); |
- runner.SetDisableCsrss(false); |
- |
- base::FilePath cmd; |
- EXPECT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &cmd)); |
- cmd = cmd.Append(L"calc.exe"); |
- |
- std::wstring test_command = L"TestChildProcess "; |
- test_command += cmd.value().c_str(); |
- |
- EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(test_command.c_str())); |
-} |
- |
-// This test validates that when the sandboxed target within a job spawns a |
-// child process and the target process exits abnormally, the broker correctly |
-// handles the JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS message. |
-// Because this involves spawning a child process from the target process and is |
-// very similar to the above CheckChildProcess* tests, this test is here rather |
-// than elsewhere closer to the other Job tests. |
-TEST(ProcessMitigationsTest, CheckChildProcessAbnormalExit) { |
- TestRunner runner; |
- sandbox::TargetPolicy* policy = runner.GetPolicy(); |
- |
- // Set a policy that would normally allow for process creation. |
- policy->SetJobLevel(JOB_INTERACTIVE, 0); |
- policy->SetTokenLevel(USER_UNPROTECTED, USER_UNPROTECTED); |
- runner.SetDisableCsrss(false); |
- |
- base::FilePath cmd; |
- EXPECT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &cmd)); |
- cmd = cmd.Append(L"calc.exe"); |
- |
- std::wstring test_command(base::StringPrintf(L"TestChildProcess %ls 0x%08X", |
- cmd.value().c_str(), |
- STATUS_ACCESS_VIOLATION)); |
- |
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str())); |
-} |
- |
-} // namespace sandbox |