blob: 4c7dba471c4db5d6863662805b04c1cd63178cf0 [file] [log] [blame]
// Copyright 2017 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 <windows.h>
#include <d3d9.h>
#include <initguid.h>
#include <opmapi.h>
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.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/tests/common/controller.h"
#include "sandbox/win/tests/integration_tests/integration_tests_common.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
//------------------------------------------------------------------------------
// Internal Functions
//------------------------------------------------------------------------------
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, base::string16> EnumerateMonitors() {
std::map<HMONITOR, base::string16> 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, base::string16> GetTestMonitors() {
std::map<HMONITOR, base::string16> result;
HMONITOR_ENTRY(0x11111111);
HMONITOR_ENTRY(0x22222222);
HMONITOR_ENTRY(0x44444444);
HMONITOR_ENTRY(0x88888888);
return result;
}
base::string16 UnicodeStringToString(PUNICODE_STRING name) {
return base::string16(
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) {
base::string16 name = UnicodeStringToString(device_name);
std::map<HMONITOR, base::string16> 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, base::string16> 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;
}
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(&params, &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 sandbox::SBOX_TEST_FIRST_ERROR;
if (!RunTestsOnVideoOutputFinishInitialization(monitor_index, video_output))
return sandbox::SBOX_TEST_SECOND_ERROR;
if (!RunTestsOnVideoOutputConfigure(monitor_index, video_output))
return sandbox::SBOX_TEST_THIRD_ERROR;
if (!RunTestsOnVideoOutputGetInformation(monitor_index, video_output))
return sandbox::SBOX_TEST_FOURTH_ERROR;
return sandbox::SBOX_TEST_SUCCEEDED;
}
} // namespace
namespace sandbox {
//------------------------------------------------------------------------------
// Exported functions called by child test processes.
//------------------------------------------------------------------------------
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;
base::string16 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;
}
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;
}
//------------------------------------------------------------------------------
// Exported Win32k Lockdown Tests
//------------------------------------------------------------------------------
// 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(ProcessMitigationsWin32kTest, CheckWin8LockDownFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
base::string16 test_policy_command = L"CheckPolicy ";
test_policy_command += std::to_wstring(TESTPOLICY_WIN32K);
TestRunner runner;
sandbox::TargetPolicy* policy = runner.GetPolicy();
EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_WIN32K_DISABLE),
SBOX_ALL_OK);
EXPECT_NE(SBOX_TEST_SUCCEEDED, runner.RunTest(test_policy_command.c_str()));
}
// 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(ProcessMitigationsWin32kTest, CheckWin8LockDownSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
base::string16 test_policy_command = L"CheckPolicy ";
test_policy_command += std::to_wstring(TESTPOLICY_WIN32K);
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(test_policy_command.c_str()));
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(ProcessMitigationsWin32kTest, CheckWin8Redirection) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
base::string16 test_policy_command = L"CheckPolicy ";
test_policy_command += std::to_wstring(TESTPOLICY_WIN32K);
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(test_policy_command.c_str()));
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"));
}
} // namespace sandbox