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

Unified Diff: sandbox/win/src/process_mitigations_win32k_policy.cc

Issue 1856993003: Implement sandbox hooks to forward OPM related GDI system calls. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed header Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sandbox/win/src/process_mitigations_win32k_policy.h ('k') | sandbox/win/src/sandbox_policy.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..6d12d828dba90f4c25b0806f900d603a12c59643 100644
--- a/sandbox/win/src/process_mitigations_win32k_policy.cc
+++ b/sandbox/win/src/process_mitigations_win32k_policy.cc
@@ -2,10 +2,141 @@
// 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"));
+ }
+ 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 GetExportedFunc(const wchar_t* libname, const char* name) {
+ OverrideForTestFunction test_override =
+ ProcessMitigationsWin32KLockdownPolicy::GetOverrideForTestCallback();
+ if (test_override)
+ return reinterpret_cast<T>(test_override(name));
+
+ static T func = nullptr;
+ if (!func) {
+ func =
+ reinterpret_cast<T>(::GetProcAddress(::GetModuleHandle(libname), name));
+ DCHECK(!!func);
+ }
+ return func;
+}
+
+#define GDIFUNC(name) GetExportedFunc<name##Function>(L"gdi32.dll", #name)
+#define USERFUNC(name) GetExportedFunc<name##Function>(L"user32.dll", #name)
+
+struct ValidateMonitorParams {
+ HMONITOR monitor;
+ base::string16 device_name;
+ bool result;
+};
+
+bool GetMonitorDeviceName(HMONITOR monitor, base::string16* device_name) {
+ MONITORINFOEXW monitor_info = {};
+ monitor_info.cbSize = sizeof(monitor_info);
+ if (!USERFUNC(GetMonitorInfoW)(monitor, &monitor_info))
+ return false;
+ if (monitor_info.szDevice[CCHDEVICENAME - 1] != 0)
+ return false;
+ *device_name = monitor_info.szDevice;
+ return true;
+}
+
+BOOL CALLBACK ValidateMonitorEnumProc(HMONITOR monitor,
+ HDC,
+ LPRECT,
+ LPARAM data) {
+ ValidateMonitorParams* valid_params =
+ reinterpret_cast<ValidateMonitorParams*>(data);
+ base::string16 device_name;
+ bool result = false;
+ if (valid_params->device_name.empty()) {
+ result = monitor == valid_params->monitor;
+ } else if (GetMonitorDeviceName(monitor, &device_name)) {
+ result = device_name == valid_params->device_name;
+ }
+ valid_params->result = result;
+ if (!result)
+ return TRUE;
+ return FALSE;
+}
+
+bool IsValidMonitorOrDeviceName(HMONITOR monitor, const wchar_t* device_name) {
+ ValidateMonitorParams params = {};
+ params.monitor = monitor;
+ if (device_name)
+ params.device_name = device_name;
+ USERFUNC(EnumDisplayMonitors)
+ (nullptr, nullptr, ValidateMonitorEnumProc,
+ reinterpret_cast<LPARAM>(&params));
+ return params.result;
+}
+
+} // namespace
+
+OverrideForTestFunction
+ ProcessMitigationsWin32KLockdownPolicy::override_callback_;
+
bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
const wchar_t* name,
TargetPolicy::Semantics semantics,
@@ -17,8 +148,263 @@ 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};
+ USERFUNC(EnumDisplayMonitors)
+ (nullptr, nullptr, DisplayMonitorEnumProc, reinterpret_cast<LPARAM>(&state));
+ return state.monitor_list_pos;
+}
+
+BOOL ProcessMitigationsWin32KLockdownPolicy::GetMonitorInfoAction(
+ const ClientInfo& client_info,
+ HMONITOR monitor,
+ MONITORINFO* monitor_info_ptr) {
+ if (!IsValidMonitorOrDeviceName(monitor, nullptr))
+ return FALSE;
+ MONITORINFOEXW monitor_info = {};
+ monitor_info.cbSize = sizeof(MONITORINFOEXW);
+
+ BOOL success = USERFUNC(GetMonitorInfoW)(
+ monitor, reinterpret_cast<MONITORINFO*>(&monitor_info));
+ if (success)
+ memcpy(monitor_info_ptr, &monitor_info, sizeof(monitor_info));
+ return success;
+}
+
+NTSTATUS ProcessMitigationsWin32KLockdownPolicy::
+ GetSuggestedOPMProtectedOutputArraySizeAction(
+ const ClientInfo& client_info,
+ const base::string16& device_name,
+ uint32_t* suggested_array_size) {
+ if (!IsValidMonitorOrDeviceName(nullptr, device_name.c_str())) {
+ return STATUS_ACCESS_DENIED;
+ }
+ UNICODE_STRING unicode_device_name;
+ StringToUnicodeString(&unicode_device_name, device_name);
+ DWORD suggested_array_size_dword = 0;
+ NTSTATUS status = GDIFUNC(GetSuggestedOPMProtectedOutputArraySize)(
+ &unicode_device_name, &suggested_array_size_dword);
+ if (!status)
+ *suggested_array_size = suggested_array_size_dword;
+ return status;
+}
+
+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) {
+ if (!IsValidMonitorOrDeviceName(nullptr, device_name.c_str())) {
+ return STATUS_ACCESS_DENIED;
+ }
+
+ 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) {
+ if (!IsValidMonitorOrDeviceName(nullptr, device_name.c_str())) {
+ return STATUS_ACCESS_DENIED;
+ }
+ 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) {
+ if (!IsValidMonitorOrDeviceName(nullptr, device_name.c_str())) {
+ return STATUS_ACCESS_DENIED;
+ }
+ 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::GetCertificateSizeByHandleAction(
+ const ClientInfo& client_info,
+ HANDLE protected_output,
+ uint32_t* cert_size) {
+ auto get_certificate_size_func = GDIFUNC(GetCertificateSizeByHandle);
+ if (get_certificate_size_func) {
+ return get_certificate_size_func(protected_output, DXGKMDT_OPM_CERTIFICATE,
+ reinterpret_cast<DWORD*>(cert_size));
+ }
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateByHandleAction(
+ const ClientInfo& client_info,
+ HANDLE protected_output,
+ BYTE* cert_data,
+ uint32_t cert_size) {
+ auto get_certificate_func = GDIFUNC(GetCertificateByHandle);
+ if (get_certificate_func) {
+ return get_certificate_func(protected_output, DXGKMDT_OPM_CERTIFICATE,
+ cert_data, cert_size);
+ }
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+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));
+}
+
+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_ptr) {
+ DXGKMDT_OPM_CONFIGURE_PARAMETERS parameters;
+ memcpy(&parameters, parameters_ptr, sizeof(parameters));
+ if (parameters.guidSetting != DXGKMDT_OPM_SET_PROTECTION_LEVEL ||
+ parameters.cbParametersSize !=
+ sizeof(DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS)) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS prot_level;
+ memcpy(&prot_level, parameters.abParameters, sizeof(prot_level));
+ if (prot_level.Reserved || prot_level.Reserved2)
+ return STATUS_INVALID_PARAMETER;
+
+ if (prot_level.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_HDCP &&
+ prot_level.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_DPCP) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Protection levels are same for HDCP and DPCP.
+ if (prot_level.ulProtectionLevel != DXGKMDT_OPM_HDCP_OFF &&
+ prot_level.ulProtectionLevel != DXGKMDT_OPM_HDCP_ON) {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ return GDIFUNC(ConfigureOPMProtectedOutput)(protected_output, &parameters, 0,
+ nullptr);
+}
+
+NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMInformationAction(
+ const ClientInfo& client_info,
+ HANDLE protected_output,
+ void* parameters_ptr,
+ void* requested_info_ptr) {
+ DXGKMDT_OPM_GET_INFO_PARAMETERS parameters;
+ memcpy(&parameters, parameters_ptr, sizeof(parameters));
+
+ bool valid_parameters = false;
+ // Validate sizes based on the type being requested.
+ if ((parameters.guidInformation == DXGKMDT_OPM_GET_CONNECTOR_TYPE ||
+ parameters.guidInformation ==
+ DXGKMDT_OPM_GET_SUPPORTED_PROTECTION_TYPES) &&
+ parameters.cbParametersSize == 0) {
+ valid_parameters = true;
+ } else if ((parameters.guidInformation ==
+ DXGKMDT_OPM_GET_VIRTUAL_PROTECTION_LEVEL ||
+ parameters.guidInformation ==
+ DXGKMDT_OPM_GET_ACTUAL_PROTECTION_LEVEL) &&
+ parameters.cbParametersSize == sizeof(uint32_t)) {
+ uint32_t param_value;
+ memcpy(&param_value, parameters.abParameters, sizeof(param_value));
+ 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;
+ DXGKMDT_OPM_REQUESTED_INFORMATION requested_info = {};
+ NTSTATUS status = GDIFUNC(GetOPMInformation)(protected_output, &parameters,
+ &requested_info);
+ if (!status)
+ memcpy(requested_info_ptr, &requested_info, sizeof(requested_info));
+
+ return status;
+}
+
+NTSTATUS
+ProcessMitigationsWin32KLockdownPolicy::DestroyOPMProtectedOutputAction(
+ HANDLE protected_output) {
+ return GDIFUNC(DestroyOPMProtectedOutput)(protected_output);
+}
+
+void ProcessMitigationsWin32KLockdownPolicy::SetOverrideForTestCallback(
+ OverrideForTestFunction callback) {
+ override_callback_ = callback;
+}
+
+OverrideForTestFunction
+ProcessMitigationsWin32KLockdownPolicy::GetOverrideForTestCallback() {
+ return override_callback_;
+}
+
} // namespace sandbox
« no previous file with comments | « sandbox/win/src/process_mitigations_win32k_policy.h ('k') | sandbox/win/src/sandbox_policy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698