Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | |
| 6 | |
| 7 #include "sandbox/win/src/process_mitigations_win32k_interception.h" | |
| 5 #include "sandbox/win/src/process_mitigations_win32k_policy.h" | 8 #include "sandbox/win/src/process_mitigations_win32k_policy.h" |
| 6 | 9 |
| 7 namespace sandbox { | 10 namespace sandbox { |
| 8 | 11 |
| 12 namespace { | |
| 13 | |
| 14 // Define GUIDs for OPM APIs | |
| 15 const GUID DXGKMDT_OPM_GET_CONNECTOR_TYPE = { | |
| 16 0x81d0bfd5, | |
| 17 0x6afe, | |
| 18 0x48c2, | |
| 19 {0x99, 0xc0, 0x95, 0xa0, 0x8f, 0x97, 0xc5, 0xda}}; | |
| 20 const GUID DXGKMDT_OPM_GET_SUPPORTED_PROTECTION_TYPES = { | |
| 21 0x38f2a801, | |
| 22 0x9a6c, | |
| 23 0x48bb, | |
| 24 {0x91, 0x07, 0xb6, 0x69, 0x6e, 0x6f, 0x17, 0x97}}; | |
| 25 const GUID DXGKMDT_OPM_GET_VIRTUAL_PROTECTION_LEVEL = { | |
| 26 0xb2075857, | |
| 27 0x3eda, | |
| 28 0x4d5d, | |
| 29 {0x88, 0xdb, 0x74, 0x8f, 0x8c, 0x1a, 0x05, 0x49}}; | |
| 30 const GUID DXGKMDT_OPM_GET_ACTUAL_PROTECTION_LEVEL = { | |
| 31 0x1957210a, | |
| 32 0x7766, | |
| 33 0x452a, | |
| 34 {0xb9, 0x9a, 0xd2, 0x7a, 0xed, 0x54, 0xf0, 0x3a}}; | |
| 35 const GUID DXGKMDT_OPM_SET_PROTECTION_LEVEL = { | |
| 36 0x9bb9327c, | |
| 37 0x4eb5, | |
| 38 0x4727, | |
| 39 {0x9f, 0x00, 0xb4, 0x2b, 0x09, 0x19, 0xc0, 0xda}}; | |
| 40 | |
| 41 void StringToUnicodeString(PUNICODE_STRING unicode_string, | |
| 42 const base::string16& device_name) { | |
| 43 static RtlInitUnicodeStringFunction RtlInitUnicodeString; | |
| 44 if (!RtlInitUnicodeString) { | |
| 45 HMODULE ntdll = ::GetModuleHandle(kNtdllName); | |
| 46 RtlInitUnicodeString = reinterpret_cast<RtlInitUnicodeStringFunction>( | |
| 47 GetProcAddress(ntdll, "RtlInitUnicodeString")); | |
| 48 DCHECK(!!RtlInitUnicodeString); | |
| 49 } | |
| 50 RtlInitUnicodeString(unicode_string, device_name.c_str()); | |
| 51 } | |
| 52 | |
| 53 struct MonitorListState { | |
| 54 HMONITOR* monitor_list; | |
| 55 uint32_t monitor_list_size; | |
| 56 uint32_t monitor_list_pos; | |
| 57 }; | |
| 58 | |
| 59 BOOL CALLBACK DisplayMonitorEnumProc(HMONITOR monitor, | |
| 60 HDC hdc_monitor, | |
| 61 LPRECT rect_monitor, | |
| 62 LPARAM data) { | |
| 63 MonitorListState* state = reinterpret_cast<MonitorListState*>(data); | |
| 64 if (state->monitor_list_pos >= state->monitor_list_size) | |
| 65 return FALSE; | |
| 66 state->monitor_list[state->monitor_list_pos++] = monitor; | |
| 67 return TRUE; | |
| 68 } | |
| 69 | |
| 70 template <typename T> | |
| 71 T GetGdi32Func(const char* name) { | |
| 72 static T func = nullptr; | |
| 73 if (!func) { | |
| 74 func = reinterpret_cast<T>( | |
| 75 ::GetProcAddress(::GetModuleHandle(L"gdi32.dll"), name)); | |
| 76 DCHECK(!!func); | |
| 77 } | |
| 78 return func; | |
| 79 } | |
| 80 | |
| 81 #define GDIFUNC(name) GetGdi32Func<name##Function>(#name) | |
| 82 | |
| 83 } // namespace | |
| 84 | |
| 9 bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( | 85 bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( |
| 10 const wchar_t* name, | 86 const wchar_t* name, |
| 11 TargetPolicy::Semantics semantics, | 87 TargetPolicy::Semantics semantics, |
| 12 LowLevelPolicy* policy) { | 88 LowLevelPolicy* policy) { |
| 13 PolicyRule rule(FAKE_SUCCESS); | 89 PolicyRule rule(FAKE_SUCCESS); |
| 14 if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule)) | 90 if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule)) |
| 15 return false; | 91 return false; |
| 16 if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule)) | 92 if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule)) |
| 17 return false; | 93 return false; |
| 18 if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule)) | 94 if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule)) |
| 19 return false; | 95 return false; |
| 96 if (semantics != TargetPolicy::IMPLEMENT_OPM_APIS) | |
| 97 return true; | |
| 98 if (!policy->AddRule(IPC_USER_ENUMDISPLAYMONITORS_TAG, &rule)) | |
| 99 return false; | |
| 100 if (!policy->AddRule(IPC_USER_ENUMDISPLAYDEVICES_TAG, &rule)) | |
| 101 return false; | |
| 102 if (!policy->AddRule(IPC_USER_GETMONITORINFO_TAG, &rule)) | |
| 103 return false; | |
| 104 if (!policy->AddRule(IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG, &rule)) | |
| 105 return false; | |
| 106 if (!policy->AddRule(IPC_GDI_GETCERTIFICATE_TAG, &rule)) | |
| 107 return false; | |
| 108 if (!policy->AddRule(IPC_GDI_GETCERTIFICATESIZE_TAG, &rule)) | |
| 109 return false; | |
| 110 if (!policy->AddRule(IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG, &rule)) | |
| 111 return false; | |
| 112 if (!policy->AddRule(IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG, &rule)) | |
| 113 return false; | |
| 114 if (!policy->AddRule(IPC_GDI_GETOPMINFORMATION_TAG, &rule)) | |
| 115 return false; | |
| 116 if (!policy->AddRule(IPC_GDI_GETOPMRANDOMNUMBER_TAG, &rule)) | |
| 117 return false; | |
| 118 if (!policy->AddRule(IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG, | |
| 119 &rule)) | |
| 120 return false; | |
| 121 if (!policy->AddRule(IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG, &rule)) | |
| 122 return false; | |
| 20 return true; | 123 return true; |
| 21 } | 124 } |
| 22 | 125 |
| 126 uint32_t ProcessMitigationsWin32KLockdownPolicy::EnumDisplayMonitorsAction( | |
| 127 const ClientInfo& client_info, | |
| 128 HMONITOR* monitor_list, | |
| 129 uint32_t monitor_list_size) { | |
| 130 MonitorListState state = {monitor_list, monitor_list_size, 0}; | |
| 131 EnumDisplayMonitors(nullptr, nullptr, DisplayMonitorEnumProc, | |
| 132 reinterpret_cast<LPARAM>(&state)); | |
| 133 return state.monitor_list_pos; | |
| 134 } | |
| 135 | |
| 136 NTSTATUS ProcessMitigationsWin32KLockdownPolicy:: | |
| 137 GetSuggestedOPMProtectedOutputArraySizeAction( | |
| 138 const ClientInfo& client_info, | |
| 139 const base::string16& device_name, | |
| 140 uint32_t* suggested_array_size) { | |
| 141 UNICODE_STRING unicode_device_name; | |
| 142 StringToUnicodeString(&unicode_device_name, device_name); | |
| 143 return GDIFUNC(GetSuggestedOPMProtectedOutputArraySize)( | |
| 144 &unicode_device_name, reinterpret_cast<DWORD*>(suggested_array_size)); | |
| 145 } | |
| 146 | |
| 147 NTSTATUS | |
| 148 ProcessMitigationsWin32KLockdownPolicy::CreateOPMProtectedOutputsAction( | |
| 149 const ClientInfo& client_info, | |
| 150 const base::string16& device_name, | |
| 151 HANDLE* protected_outputs, | |
| 152 uint32_t array_input_size, | |
| 153 uint32_t* array_output_size) { | |
| 154 UNICODE_STRING unicode_device_name; | |
| 155 StringToUnicodeString(&unicode_device_name, device_name); | |
| 156 DWORD output_size = 0; | |
| 157 | |
| 158 NTSTATUS status = GDIFUNC(CreateOPMProtectedOutputs)( | |
| 159 &unicode_device_name, DXGKMDT_OPM_VOS_OPM_SEMANTICS, array_input_size, | |
| 160 &output_size, | |
| 161 reinterpret_cast<OPM_PROTECTED_OUTPUT_HANDLE*>(protected_outputs)); | |
| 162 if (!status) | |
| 163 *array_output_size = output_size; | |
| 164 return status; | |
| 165 } | |
| 166 | |
| 167 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateSizeAction( | |
| 168 const ClientInfo& client_info, | |
| 169 const base::string16& device_name, | |
| 170 uint32_t* cert_size) { | |
| 171 UNICODE_STRING unicode_device_name; | |
| 172 StringToUnicodeString(&unicode_device_name, device_name); | |
| 173 | |
| 174 return GDIFUNC(GetCertificateSize)(&unicode_device_name, | |
| 175 DXGKMDT_OPM_CERTIFICATE, | |
| 176 reinterpret_cast<DWORD*>(cert_size)); | |
| 177 } | |
| 178 | |
| 179 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateAction( | |
| 180 const ClientInfo& client_info, | |
| 181 const base::string16& device_name, | |
| 182 BYTE* cert_data, | |
| 183 uint32_t cert_size) { | |
| 184 UNICODE_STRING unicode_device_name; | |
| 185 StringToUnicodeString(&unicode_device_name, device_name); | |
| 186 | |
| 187 return GDIFUNC(GetCertificate)(&unicode_device_name, DXGKMDT_OPM_CERTIFICATE, | |
| 188 cert_data, cert_size); | |
| 189 } | |
| 190 | |
| 191 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMRandomNumberAction( | |
| 192 const ClientInfo& client_info, | |
| 193 HANDLE protected_output, | |
| 194 void* random_number) { | |
| 195 return GDIFUNC(GetOPMRandomNumber)( | |
| 196 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.
| |
| 197 } | |
| 198 | |
| 199 NTSTATUS ProcessMitigationsWin32KLockdownPolicy:: | |
| 200 SetOPMSigningKeyAndSequenceNumbersAction(const ClientInfo& client_info, | |
| 201 HANDLE protected_output, | |
| 202 void* parameters) { | |
| 203 return GDIFUNC(SetOPMSigningKeyAndSequenceNumbers)( | |
| 204 protected_output, | |
| 205 static_cast<DXGKMDT_OPM_ENCRYPTED_PARAMETERS*>(parameters)); | |
| 206 } | |
| 207 | |
| 208 NTSTATUS | |
| 209 ProcessMitigationsWin32KLockdownPolicy::ConfigureOPMProtectedOutputAction( | |
| 210 const ClientInfo& client_info, | |
| 211 HANDLE protected_output, | |
| 212 void* parameters) { | |
| 213 DXGKMDT_OPM_CONFIGURE_PARAMETERS config; | |
| 214 memcpy(&config, parameters, sizeof(DXGKMDT_OPM_CONFIGURE_PARAMETERS)); | |
| 215 if (config.guidSetting != DXGKMDT_OPM_SET_PROTECTION_LEVEL || | |
| 216 config.cbParametersSize != | |
| 217 sizeof(DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS)) { | |
| 218 return STATUS_INVALID_PARAMETER; | |
| 219 } | |
| 220 | |
| 221 DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS params; | |
| 222 memcpy(¶ms, config.abParameters, | |
| 223 sizeof(DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS)); | |
| 224 if (params.Reserved || params.Reserved2) | |
| 225 return STATUS_INVALID_PARAMETER; | |
| 226 | |
| 227 if (params.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_HDCP && | |
| 228 params.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_DPCP) { | |
| 229 return STATUS_INVALID_PARAMETER; | |
| 230 } | |
| 231 | |
| 232 // Protection levels are same for HDCP and DPCP. | |
| 233 if (params.ulProtectionLevel != DXGKMDT_OPM_HDCP_OFF && | |
| 234 params.ulProtectionLevel != DXGKMDT_OPM_HDCP_ON) { | |
| 235 return STATUS_INVALID_PARAMETER; | |
| 236 } | |
| 237 | |
| 238 return GDIFUNC(ConfigureOPMProtectedOutput)(protected_output, &config, 0, | |
| 239 nullptr); | |
| 240 } | |
| 241 | |
| 242 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMInformationAction( | |
| 243 const ClientInfo& client_info, | |
| 244 HANDLE protected_output, | |
| 245 void* parameters, | |
| 246 void* requested_information) { | |
| 247 DXGKMDT_OPM_GET_INFO_PARAMETERS params; | |
| 248 memcpy(¶ms, parameters, sizeof(DXGKMDT_OPM_GET_INFO_PARAMETERS)); | |
| 249 | |
| 250 bool valid_parameters = false; | |
| 251 // Validate sizes based on the type being requested. | |
| 252 if ((params.guidInformation == DXGKMDT_OPM_GET_CONNECTOR_TYPE || | |
| 253 params.guidInformation == DXGKMDT_OPM_GET_SUPPORTED_PROTECTION_TYPES) && | |
| 254 params.cbParametersSize == 0) { | |
| 255 valid_parameters = true; | |
| 256 } else if ((params.guidInformation == | |
| 257 DXGKMDT_OPM_GET_VIRTUAL_PROTECTION_LEVEL || | |
| 258 params.guidInformation == | |
| 259 DXGKMDT_OPM_GET_ACTUAL_PROTECTION_LEVEL) && | |
| 260 params.cbParametersSize == sizeof(uint32_t)) { | |
| 261 uint32_t param_value; | |
| 262 memcpy(¶m_value, params.abParameters, sizeof(uint32_t)); | |
| 263 if (param_value == DXGKMDT_OPM_PROTECTION_TYPE_HDCP || | |
| 264 param_value == DXGKMDT_OPM_PROTECTION_TYPE_DPCP) { | |
| 265 valid_parameters = true; | |
| 266 } | |
| 267 } | |
| 268 if (!valid_parameters) | |
| 269 return STATUS_INVALID_PARAMETER; | |
| 270 | |
| 271 return GDIFUNC(GetOPMInformation)( | |
| 272 protected_output, ¶ms, | |
| 273 static_cast<DXGKMDT_OPM_REQUESTED_INFORMATION*>(requested_information)); | |
| 274 } | |
| 275 | |
| 276 NTSTATUS | |
| 277 ProcessMitigationsWin32KLockdownPolicy::DestroyOPMProtectedOutputAction( | |
| 278 HANDLE protected_output) { | |
| 279 return GDIFUNC(DestroyOPMProtectedOutput)(protected_output); | |
| 280 } | |
| 281 | |
| 23 } // namespace sandbox | 282 } // namespace sandbox |
| 24 | 283 |
| OLD | NEW |