Chromium Code Reviews| Index: sandbox/win/src/process_mitigations_win32k_policy.cc |
| diff --git a/sandbox/win/src/process_mitigations_win32k_policy.cc b/sandbox/win/src/process_mitigations_win32k_policy.cc |
| index af18c5413c2815499f21e413403d6f9fd082daec..4e5c01f13d608d07d5d13ae9666fe7d4e94be4c3 100644 |
| --- a/sandbox/win/src/process_mitigations_win32k_policy.cc |
| +++ b/sandbox/win/src/process_mitigations_win32k_policy.cc |
| @@ -2,10 +2,86 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include <stddef.h> |
| + |
| +#include "sandbox/win/src/process_mitigations_win32k_interception.h" |
| #include "sandbox/win/src/process_mitigations_win32k_policy.h" |
| namespace sandbox { |
| +namespace { |
| + |
| +// Define GUIDs for OPM APIs |
| +const GUID DXGKMDT_OPM_GET_CONNECTOR_TYPE = { |
| + 0x81d0bfd5, |
| + 0x6afe, |
| + 0x48c2, |
| + {0x99, 0xc0, 0x95, 0xa0, 0x8f, 0x97, 0xc5, 0xda}}; |
| +const GUID DXGKMDT_OPM_GET_SUPPORTED_PROTECTION_TYPES = { |
| + 0x38f2a801, |
| + 0x9a6c, |
| + 0x48bb, |
| + {0x91, 0x07, 0xb6, 0x69, 0x6e, 0x6f, 0x17, 0x97}}; |
| +const GUID DXGKMDT_OPM_GET_VIRTUAL_PROTECTION_LEVEL = { |
| + 0xb2075857, |
| + 0x3eda, |
| + 0x4d5d, |
| + {0x88, 0xdb, 0x74, 0x8f, 0x8c, 0x1a, 0x05, 0x49}}; |
| +const GUID DXGKMDT_OPM_GET_ACTUAL_PROTECTION_LEVEL = { |
| + 0x1957210a, |
| + 0x7766, |
| + 0x452a, |
| + {0xb9, 0x9a, 0xd2, 0x7a, 0xed, 0x54, 0xf0, 0x3a}}; |
| +const GUID DXGKMDT_OPM_SET_PROTECTION_LEVEL = { |
| + 0x9bb9327c, |
| + 0x4eb5, |
| + 0x4727, |
| + {0x9f, 0x00, 0xb4, 0x2b, 0x09, 0x19, 0xc0, 0xda}}; |
| + |
| +void StringToUnicodeString(PUNICODE_STRING unicode_string, |
| + const base::string16& device_name) { |
| + static RtlInitUnicodeStringFunction RtlInitUnicodeString; |
| + if (!RtlInitUnicodeString) { |
| + HMODULE ntdll = ::GetModuleHandle(kNtdllName); |
| + RtlInitUnicodeString = reinterpret_cast<RtlInitUnicodeStringFunction>( |
| + GetProcAddress(ntdll, "RtlInitUnicodeString")); |
| + DCHECK(!!RtlInitUnicodeString); |
| + } |
| + RtlInitUnicodeString(unicode_string, device_name.c_str()); |
| +} |
| + |
| +struct MonitorListState { |
| + HMONITOR* monitor_list; |
| + uint32_t monitor_list_size; |
| + uint32_t monitor_list_pos; |
| +}; |
| + |
| +BOOL CALLBACK DisplayMonitorEnumProc(HMONITOR monitor, |
| + HDC hdc_monitor, |
| + LPRECT rect_monitor, |
| + LPARAM data) { |
| + MonitorListState* state = reinterpret_cast<MonitorListState*>(data); |
| + if (state->monitor_list_pos >= state->monitor_list_size) |
| + return FALSE; |
| + state->monitor_list[state->monitor_list_pos++] = monitor; |
| + return TRUE; |
| +} |
| + |
| +template <typename T> |
| +T GetGdi32Func(const char* name) { |
| + static T func = nullptr; |
| + if (!func) { |
| + func = reinterpret_cast<T>( |
| + ::GetProcAddress(::GetModuleHandle(L"gdi32.dll"), name)); |
| + DCHECK(!!func); |
| + } |
| + return func; |
| +} |
| + |
| +#define GDIFUNC(name) GetGdi32Func<name##Function>(#name) |
| + |
| +} // namespace |
| + |
| bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( |
| const wchar_t* name, |
| TargetPolicy::Semantics semantics, |
| @@ -17,8 +93,191 @@ bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( |
| return false; |
| if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule)) |
| return false; |
| + if (semantics != TargetPolicy::IMPLEMENT_OPM_APIS) |
| + return true; |
| + if (!policy->AddRule(IPC_USER_ENUMDISPLAYMONITORS_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_USER_ENUMDISPLAYDEVICES_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_USER_GETMONITORINFO_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_GETCERTIFICATE_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_GETCERTIFICATESIZE_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_GETOPMINFORMATION_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_GETOPMRANDOMNUMBER_TAG, &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG, |
| + &rule)) |
| + return false; |
| + if (!policy->AddRule(IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG, &rule)) |
| + return false; |
| return true; |
| } |
| +uint32_t ProcessMitigationsWin32KLockdownPolicy::EnumDisplayMonitorsAction( |
| + const ClientInfo& client_info, |
| + HMONITOR* monitor_list, |
| + uint32_t monitor_list_size) { |
| + MonitorListState state = {monitor_list, monitor_list_size, 0}; |
| + EnumDisplayMonitors(nullptr, nullptr, DisplayMonitorEnumProc, |
| + reinterpret_cast<LPARAM>(&state)); |
| + return state.monitor_list_pos; |
| +} |
| + |
| +NTSTATUS ProcessMitigationsWin32KLockdownPolicy:: |
| + GetSuggestedOPMProtectedOutputArraySizeAction( |
| + const ClientInfo& client_info, |
| + const base::string16& device_name, |
| + uint32_t* suggested_array_size) { |
| + UNICODE_STRING unicode_device_name; |
| + StringToUnicodeString(&unicode_device_name, device_name); |
| + return GDIFUNC(GetSuggestedOPMProtectedOutputArraySize)( |
| + &unicode_device_name, reinterpret_cast<DWORD*>(suggested_array_size)); |
| +} |
| + |
| +NTSTATUS |
| +ProcessMitigationsWin32KLockdownPolicy::CreateOPMProtectedOutputsAction( |
| + const ClientInfo& client_info, |
| + const base::string16& device_name, |
| + HANDLE* protected_outputs, |
| + uint32_t array_input_size, |
| + uint32_t* array_output_size) { |
| + UNICODE_STRING unicode_device_name; |
| + StringToUnicodeString(&unicode_device_name, device_name); |
| + DWORD output_size = 0; |
| + |
| + NTSTATUS status = GDIFUNC(CreateOPMProtectedOutputs)( |
| + &unicode_device_name, DXGKMDT_OPM_VOS_OPM_SEMANTICS, array_input_size, |
| + &output_size, |
| + reinterpret_cast<OPM_PROTECTED_OUTPUT_HANDLE*>(protected_outputs)); |
| + if (!status) |
| + *array_output_size = output_size; |
| + return status; |
| +} |
| + |
| +NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateSizeAction( |
| + const ClientInfo& client_info, |
| + const base::string16& device_name, |
| + uint32_t* cert_size) { |
| + UNICODE_STRING unicode_device_name; |
| + StringToUnicodeString(&unicode_device_name, device_name); |
| + |
| + return GDIFUNC(GetCertificateSize)(&unicode_device_name, |
| + DXGKMDT_OPM_CERTIFICATE, |
| + reinterpret_cast<DWORD*>(cert_size)); |
| +} |
| + |
| +NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateAction( |
| + const ClientInfo& client_info, |
| + const base::string16& device_name, |
| + BYTE* cert_data, |
| + uint32_t cert_size) { |
| + UNICODE_STRING unicode_device_name; |
| + StringToUnicodeString(&unicode_device_name, device_name); |
| + |
| + return GDIFUNC(GetCertificate)(&unicode_device_name, DXGKMDT_OPM_CERTIFICATE, |
| + cert_data, cert_size); |
| +} |
| + |
| +NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMRandomNumberAction( |
| + const ClientInfo& client_info, |
| + HANDLE protected_output, |
| + void* random_number) { |
| + return GDIFUNC(GetOPMRandomNumber)( |
| + protected_output, static_cast<DXGKMDT_OPM_RANDOM_NUMBER*>(random_number)); |
|
Will Harris
2016/04/05 03:49:02
reinterpret_cast
Will Harris
2016/04/11 21:23:02
actually static_cast here is fine.
|
| +} |
| + |
| +NTSTATUS ProcessMitigationsWin32KLockdownPolicy:: |
| + SetOPMSigningKeyAndSequenceNumbersAction(const ClientInfo& client_info, |
| + HANDLE protected_output, |
| + void* parameters) { |
| + return GDIFUNC(SetOPMSigningKeyAndSequenceNumbers)( |
| + protected_output, |
| + static_cast<DXGKMDT_OPM_ENCRYPTED_PARAMETERS*>(parameters)); |
| +} |
| + |
| +NTSTATUS |
| +ProcessMitigationsWin32KLockdownPolicy::ConfigureOPMProtectedOutputAction( |
| + const ClientInfo& client_info, |
| + HANDLE protected_output, |
| + void* parameters) { |
| + DXGKMDT_OPM_CONFIGURE_PARAMETERS config; |
| + memcpy(&config, parameters, sizeof(DXGKMDT_OPM_CONFIGURE_PARAMETERS)); |
| + if (config.guidSetting != DXGKMDT_OPM_SET_PROTECTION_LEVEL || |
| + config.cbParametersSize != |
| + sizeof(DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS)) { |
| + return STATUS_INVALID_PARAMETER; |
| + } |
| + |
| + DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS params; |
| + memcpy(¶ms, config.abParameters, |
| + sizeof(DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS)); |
| + if (params.Reserved || params.Reserved2) |
| + return STATUS_INVALID_PARAMETER; |
| + |
| + if (params.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_HDCP && |
| + params.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_DPCP) { |
| + return STATUS_INVALID_PARAMETER; |
| + } |
| + |
| + // Protection levels are same for HDCP and DPCP. |
| + if (params.ulProtectionLevel != DXGKMDT_OPM_HDCP_OFF && |
| + params.ulProtectionLevel != DXGKMDT_OPM_HDCP_ON) { |
| + return STATUS_INVALID_PARAMETER; |
| + } |
| + |
| + return GDIFUNC(ConfigureOPMProtectedOutput)(protected_output, &config, 0, |
| + nullptr); |
| +} |
| + |
| +NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMInformationAction( |
| + const ClientInfo& client_info, |
| + HANDLE protected_output, |
| + void* parameters, |
| + void* requested_information) { |
| + DXGKMDT_OPM_GET_INFO_PARAMETERS params; |
| + memcpy(¶ms, parameters, sizeof(DXGKMDT_OPM_GET_INFO_PARAMETERS)); |
| + |
| + bool valid_parameters = false; |
| + // Validate sizes based on the type being requested. |
| + if ((params.guidInformation == DXGKMDT_OPM_GET_CONNECTOR_TYPE || |
| + params.guidInformation == DXGKMDT_OPM_GET_SUPPORTED_PROTECTION_TYPES) && |
| + params.cbParametersSize == 0) { |
| + valid_parameters = true; |
| + } else if ((params.guidInformation == |
| + DXGKMDT_OPM_GET_VIRTUAL_PROTECTION_LEVEL || |
| + params.guidInformation == |
| + DXGKMDT_OPM_GET_ACTUAL_PROTECTION_LEVEL) && |
| + params.cbParametersSize == sizeof(uint32_t)) { |
| + uint32_t param_value; |
| + memcpy(¶m_value, params.abParameters, sizeof(uint32_t)); |
| + if (param_value == DXGKMDT_OPM_PROTECTION_TYPE_HDCP || |
| + param_value == DXGKMDT_OPM_PROTECTION_TYPE_DPCP) { |
| + valid_parameters = true; |
| + } |
| + } |
| + if (!valid_parameters) |
| + return STATUS_INVALID_PARAMETER; |
| + |
| + return GDIFUNC(GetOPMInformation)( |
| + protected_output, ¶ms, |
| + static_cast<DXGKMDT_OPM_REQUESTED_INFORMATION*>(requested_information)); |
| +} |
| + |
| +NTSTATUS |
| +ProcessMitigationsWin32KLockdownPolicy::DestroyOPMProtectedOutputAction( |
| + HANDLE protected_output) { |
| + return GDIFUNC(DestroyOPMProtectedOutput)(protected_output); |
| +} |
| + |
| } // namespace sandbox |