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 "sandbox/win/src/process_mitigations_win32k_dispatcher.h" | 5 #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" |
| 6 |
| 7 #include <algorithm> |
| 8 |
| 9 #include "base/memory/shared_memory.h" |
| 10 #include "base/strings/string16.h" |
6 #include "sandbox/win/src/interception.h" | 11 #include "sandbox/win/src/interception.h" |
7 #include "sandbox/win/src/interceptors.h" | 12 #include "sandbox/win/src/interceptors.h" |
8 #include "sandbox/win/src/ipc_tags.h" | 13 #include "sandbox/win/src/ipc_tags.h" |
9 #include "sandbox/win/src/process_mitigations_win32k_interception.h" | 14 #include "sandbox/win/src/process_mitigations_win32k_interception.h" |
| 15 #include "sandbox/win/src/process_mitigations_win32k_policy.h" |
10 | 16 |
11 namespace sandbox { | 17 namespace sandbox { |
12 | 18 |
| 19 namespace { |
| 20 |
| 21 struct ValidateMonitorParams { |
| 22 HMONITOR monitor; |
| 23 base::string16 device_name; |
| 24 bool result; |
| 25 }; |
| 26 |
| 27 bool GetMonitorDeviceName(HMONITOR monitor, base::string16* device_name) { |
| 28 MONITORINFOEXW monitor_info = {}; |
| 29 monitor_info.cbSize = sizeof(MONITORINFOEXW); |
| 30 if (!::GetMonitorInfoW(monitor, |
| 31 reinterpret_cast<MONITORINFO*>(&monitor_info))) |
| 32 return false; |
| 33 if (monitor_info.szDevice[CCHDEVICENAME - 1] != 0) |
| 34 return false; |
| 35 *device_name = monitor_info.szDevice; |
| 36 return true; |
| 37 } |
| 38 |
| 39 BOOL CALLBACK ValidateMonitorEnumProc(HMONITOR monitor, |
| 40 HDC, |
| 41 LPRECT, |
| 42 LPARAM data) { |
| 43 ValidateMonitorParams* valid_params = |
| 44 reinterpret_cast<ValidateMonitorParams*>(data); |
| 45 base::string16 device_name; |
| 46 bool result = false; |
| 47 if (valid_params->device_name.empty()) { |
| 48 result = monitor == valid_params->monitor; |
| 49 } else if (GetMonitorDeviceName(monitor, &device_name)) { |
| 50 result = device_name == valid_params->device_name; |
| 51 } |
| 52 valid_params->result = result; |
| 53 if (!result) |
| 54 return TRUE; |
| 55 return FALSE; |
| 56 } |
| 57 |
| 58 bool IsValidMonitorOrDeviceName(HMONITOR monitor, const wchar_t* device_name) { |
| 59 ValidateMonitorParams params = {}; |
| 60 params.monitor = monitor; |
| 61 if (device_name) |
| 62 params.device_name = device_name; |
| 63 ::EnumDisplayMonitors(nullptr, nullptr, ValidateMonitorEnumProc, |
| 64 reinterpret_cast<LPARAM>(¶ms)); |
| 65 DCHECK(params.result); |
| 66 return params.result; |
| 67 } |
| 68 |
| 69 base::SharedMemoryHandle GetSharedMemoryHandle(const ClientInfo& client_info, |
| 70 HANDLE handle) { |
| 71 HANDLE result_handle = nullptr; |
| 72 intptr_t handle_int = reinterpret_cast<intptr_t>(handle); |
| 73 if (handle_int <= 0 || |
| 74 !::DuplicateHandle(client_info.process, handle, ::GetCurrentProcess(), |
| 75 &result_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { |
| 76 result_handle = nullptr; |
| 77 } |
| 78 return base::SharedMemoryHandle(result_handle, ::GetCurrentProcessId()); |
| 79 } |
| 80 |
| 81 } // namespace |
| 82 |
| 83 ProtectedVideoOutput::~ProtectedVideoOutput() { |
| 84 ProcessMitigationsWin32KLockdownPolicy::DestroyOPMProtectedOutputAction( |
| 85 handle_); |
| 86 } |
| 87 |
| 88 scoped_refptr<ProtectedVideoOutput> |
| 89 ProcessMitigationsWin32KDispatcher::GetProtectedVideoOutput( |
| 90 HANDLE handle, |
| 91 bool destroy_output) { |
| 92 base::AutoLock lock(protected_outputs_lock_); |
| 93 scoped_refptr<ProtectedVideoOutput> result; |
| 94 auto it = protected_outputs_.find(handle); |
| 95 if (it != protected_outputs_.end()) { |
| 96 result = it->second; |
| 97 if (destroy_output) |
| 98 protected_outputs_.erase(it); |
| 99 } |
| 100 return result; |
| 101 } |
| 102 |
13 ProcessMitigationsWin32KDispatcher::ProcessMitigationsWin32KDispatcher( | 103 ProcessMitigationsWin32KDispatcher::ProcessMitigationsWin32KDispatcher( |
14 PolicyBase* policy_base) | 104 PolicyBase* policy_base) |
15 : policy_base_(policy_base) { | 105 : policy_base_(policy_base) { |
| 106 static const IPCCall enum_display_monitors_params = { |
| 107 {IPC_USER_ENUMDISPLAYMONITORS_TAG, {INOUTPTR_TYPE}}, |
| 108 reinterpret_cast<CallbackGeneric>( |
| 109 &ProcessMitigationsWin32KDispatcher::EnumDisplayMonitors)}; |
| 110 static const IPCCall get_monitor_info_params = { |
| 111 {IPC_USER_GETMONITORINFO_TAG, {VOIDPTR_TYPE, INOUTPTR_TYPE}}, |
| 112 reinterpret_cast<CallbackGeneric>( |
| 113 &ProcessMitigationsWin32KDispatcher::GetMonitorInfo)}; |
| 114 static const IPCCall get_suggested_output_size_params = { |
| 115 {IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG, {WCHAR_TYPE}}, |
| 116 reinterpret_cast<CallbackGeneric>( |
| 117 &ProcessMitigationsWin32KDispatcher:: |
| 118 GetSuggestedOPMProtectedOutputArraySize)}; |
| 119 static const IPCCall create_protected_outputs_params = { |
| 120 {IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG, {WCHAR_TYPE, INOUTPTR_TYPE}}, |
| 121 reinterpret_cast<CallbackGeneric>( |
| 122 &ProcessMitigationsWin32KDispatcher::CreateOPMProtectedOutputs)}; |
| 123 static const IPCCall get_cert_size_params = { |
| 124 {IPC_GDI_GETCERTIFICATESIZE_TAG, {WCHAR_TYPE}}, |
| 125 reinterpret_cast<CallbackGeneric>( |
| 126 &ProcessMitigationsWin32KDispatcher::GetCertificateSize)}; |
| 127 static const IPCCall get_cert_params = { |
| 128 {IPC_GDI_GETCERTIFICATE_TAG, {WCHAR_TYPE, VOIDPTR_TYPE, UINT32_TYPE}}, |
| 129 reinterpret_cast<CallbackGeneric>( |
| 130 &ProcessMitigationsWin32KDispatcher::GetCertificate)}; |
| 131 static const IPCCall destroy_protected_output_params = { |
| 132 {IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG, {VOIDPTR_TYPE}}, |
| 133 reinterpret_cast<CallbackGeneric>( |
| 134 &ProcessMitigationsWin32KDispatcher::DestroyOPMProtectedOutput)}; |
| 135 static const IPCCall get_random_number_params = { |
| 136 {IPC_GDI_GETOPMRANDOMNUMBER_TAG, {VOIDPTR_TYPE, INOUTPTR_TYPE}}, |
| 137 reinterpret_cast<CallbackGeneric>( |
| 138 &ProcessMitigationsWin32KDispatcher::GetOPMRandomNumber)}; |
| 139 static const IPCCall set_signing_key_params = { |
| 140 {IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG, |
| 141 {VOIDPTR_TYPE, INOUTPTR_TYPE}}, |
| 142 reinterpret_cast<CallbackGeneric>( |
| 143 &ProcessMitigationsWin32KDispatcher:: |
| 144 SetOPMSigningKeyAndSequenceNumbers)}; |
| 145 static const IPCCall configure_protected_output_params = { |
| 146 {IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG, {VOIDPTR_TYPE, VOIDPTR_TYPE}}, |
| 147 reinterpret_cast<CallbackGeneric>( |
| 148 &ProcessMitigationsWin32KDispatcher::ConfigureOPMProtectedOutput)}; |
| 149 static const IPCCall get_information_params = { |
| 150 {IPC_GDI_GETOPMINFORMATION_TAG, {VOIDPTR_TYPE, VOIDPTR_TYPE}}, |
| 151 reinterpret_cast<CallbackGeneric>( |
| 152 &ProcessMitigationsWin32KDispatcher::GetOPMInformation)}; |
| 153 |
| 154 ipc_calls_.push_back(enum_display_monitors_params); |
| 155 ipc_calls_.push_back(get_monitor_info_params); |
| 156 ipc_calls_.push_back(get_suggested_output_size_params); |
| 157 ipc_calls_.push_back(create_protected_outputs_params); |
| 158 ipc_calls_.push_back(get_cert_size_params); |
| 159 ipc_calls_.push_back(get_cert_params); |
| 160 ipc_calls_.push_back(destroy_protected_output_params); |
| 161 ipc_calls_.push_back(get_random_number_params); |
| 162 ipc_calls_.push_back(set_signing_key_params); |
| 163 ipc_calls_.push_back(configure_protected_output_params); |
| 164 ipc_calls_.push_back(get_information_params); |
16 } | 165 } |
17 | 166 |
| 167 ProcessMitigationsWin32KDispatcher::~ProcessMitigationsWin32KDispatcher() {} |
| 168 |
18 bool ProcessMitigationsWin32KDispatcher::SetupService( | 169 bool ProcessMitigationsWin32KDispatcher::SetupService( |
19 InterceptionManager* manager, int service) { | 170 InterceptionManager* manager, int service) { |
20 if (!(policy_base_->GetProcessMitigations() & | 171 if (!(policy_base_->GetProcessMitigations() & |
21 sandbox::MITIGATION_WIN32K_DISABLE)) { | 172 sandbox::MITIGATION_WIN32K_DISABLE)) { |
22 return false; | 173 return false; |
23 } | 174 } |
24 | 175 |
25 switch (service) { | 176 switch (service) { |
26 case IPC_GDI_GDIDLLINITIALIZE_TAG: { | 177 case IPC_GDI_GDIDLLINITIALIZE_TAG: { |
27 if (!INTERCEPT_EAT(manager, L"gdi32.dll", GdiDllInitialize, | 178 if (!INTERCEPT_EAT(manager, L"gdi32.dll", GdiDllInitialize, |
(...skipping 12 matching lines...) Expand all Loading... |
40 } | 191 } |
41 | 192 |
42 case IPC_USER_REGISTERCLASSW_TAG: { | 193 case IPC_USER_REGISTERCLASSW_TAG: { |
43 if (!INTERCEPT_EAT(manager, L"user32.dll", RegisterClassW, | 194 if (!INTERCEPT_EAT(manager, L"user32.dll", RegisterClassW, |
44 REGISTERCLASSW_ID, 8)) { | 195 REGISTERCLASSW_ID, 8)) { |
45 return false; | 196 return false; |
46 } | 197 } |
47 return true; | 198 return true; |
48 } | 199 } |
49 | 200 |
| 201 case IPC_USER_ENUMDISPLAYMONITORS_TAG: { |
| 202 if (!INTERCEPT_EAT(manager, L"user32.dll", EnumDisplayMonitors, |
| 203 ENUMDISPLAYMONITORS_ID, 20)) { |
| 204 return false; |
| 205 } |
| 206 return true; |
| 207 } |
| 208 |
| 209 case IPC_USER_ENUMDISPLAYDEVICES_TAG: { |
| 210 if (!INTERCEPT_EAT(manager, L"user32.dll", EnumDisplayDevicesA, |
| 211 ENUMDISPLAYDEVICESA_ID, 20)) { |
| 212 return false; |
| 213 } |
| 214 return true; |
| 215 } |
| 216 |
| 217 case IPC_USER_GETMONITORINFO_TAG: { |
| 218 if (!INTERCEPT_EAT(manager, L"user32.dll", GetMonitorInfoA, |
| 219 GETMONITORINFOA_ID, 12)) { |
| 220 return false; |
| 221 } |
| 222 if (!INTERCEPT_EAT(manager, L"user32.dll", GetMonitorInfoW, |
| 223 GETMONITORINFOW_ID, 12)) { |
| 224 return false; |
| 225 } |
| 226 return true; |
| 227 } |
| 228 |
| 229 case IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG: |
| 230 if (!INTERCEPT_EAT(manager, L"gdi32.dll", CreateOPMProtectedOutputs, |
| 231 CREATEOPMPROTECTEDOUTPUTS_ID, 24)) { |
| 232 return false; |
| 233 } |
| 234 return true; |
| 235 case IPC_GDI_GETCERTIFICATE_TAG: |
| 236 if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetCertificate, |
| 237 GETCERTIFICATE_ID, 20)) { |
| 238 return false; |
| 239 } |
| 240 return true; |
| 241 case IPC_GDI_GETCERTIFICATESIZE_TAG: |
| 242 if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetCertificateSize, |
| 243 GETCERTIFICATESIZE_ID, 16)) { |
| 244 return false; |
| 245 } |
| 246 return true; |
| 247 case IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG: |
| 248 if (!INTERCEPT_EAT(manager, L"gdi32.dll", DestroyOPMProtectedOutput, |
| 249 DESTROYOPMPROTECTEDOUTPUT_ID, 8)) { |
| 250 return false; |
| 251 } |
| 252 return true; |
| 253 case IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG: |
| 254 if (!INTERCEPT_EAT(manager, L"gdi32.dll", ConfigureOPMProtectedOutput, |
| 255 CONFIGUREOPMPROTECTEDOUTPUT_ID, 20)) { |
| 256 return false; |
| 257 } |
| 258 return true; |
| 259 case IPC_GDI_GETOPMINFORMATION_TAG: |
| 260 if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetOPMInformation, |
| 261 GETOPMINFORMATION_ID, 16)) { |
| 262 return false; |
| 263 } |
| 264 return true; |
| 265 case IPC_GDI_GETOPMRANDOMNUMBER_TAG: |
| 266 if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetOPMRandomNumber, |
| 267 GETOPMRANDOMNUMBER_ID, 12)) { |
| 268 return false; |
| 269 } |
| 270 return true; |
| 271 case IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG: |
| 272 if (!INTERCEPT_EAT(manager, L"gdi32.dll", |
| 273 GetSuggestedOPMProtectedOutputArraySize, |
| 274 GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_ID, 12)) { |
| 275 return false; |
| 276 } |
| 277 return true; |
| 278 case IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG: |
| 279 if (!INTERCEPT_EAT(manager, L"gdi32.dll", |
| 280 SetOPMSigningKeyAndSequenceNumbers, |
| 281 SETOPMSIGNINGKEYANDSEQUENCENUMBERS_ID, 12)) { |
| 282 return false; |
| 283 } |
| 284 return true; |
| 285 |
50 default: | 286 default: |
51 break; | 287 break; |
52 } | 288 } |
53 return false; | 289 return false; |
54 } | 290 } |
55 | 291 |
| 292 bool ProcessMitigationsWin32KDispatcher::EnumDisplayMonitors( |
| 293 IPCInfo* ipc, |
| 294 CountedBuffer* buffer) { |
| 295 if (!policy_base_->GetEnableOPMRedirection()) { |
| 296 ipc->return_info.win32_result = ERROR_ACCESS_DENIED; |
| 297 return true; |
| 298 } |
| 299 |
| 300 if (buffer->Size() != sizeof(EnumMonitorsResult)) { |
| 301 ipc->return_info.win32_result = ERROR_INVALID_PARAMETER; |
| 302 return true; |
| 303 } |
| 304 HMONITOR monitor_list[kMaxEnumMonitors] = {}; |
| 305 |
| 306 uint32_t monitor_list_count = |
| 307 ProcessMitigationsWin32KLockdownPolicy::EnumDisplayMonitorsAction( |
| 308 *ipc->client_info, monitor_list, kMaxEnumMonitors); |
| 309 DCHECK(monitor_list_count <= kMaxEnumMonitors); |
| 310 |
| 311 EnumMonitorsResult* result = |
| 312 static_cast<EnumMonitorsResult*>(buffer->Buffer()); |
| 313 for (uint32_t monitor_pos = 0; monitor_pos < monitor_list_count; |
| 314 ++monitor_pos) { |
| 315 result->monitors[monitor_pos] = monitor_list[monitor_pos]; |
| 316 } |
| 317 result->monitor_count = monitor_list_count; |
| 318 ipc->return_info.win32_result = 0; |
| 319 |
| 320 return true; |
| 321 } |
| 322 |
| 323 bool ProcessMitigationsWin32KDispatcher::GetMonitorInfo(IPCInfo* ipc, |
| 324 void* monitor, |
| 325 CountedBuffer* buffer) { |
| 326 if (!policy_base_->GetEnableOPMRedirection()) { |
| 327 ipc->return_info.win32_result = ERROR_ACCESS_DENIED; |
| 328 return true; |
| 329 } |
| 330 if (buffer->Size() < sizeof(MONITORINFO)) { |
| 331 ipc->return_info.win32_result = ERROR_INVALID_PARAMETER; |
| 332 return true; |
| 333 } |
| 334 MONITORINFO* monitor_info = static_cast<MONITORINFO*>(buffer->Buffer()); |
| 335 BOOL success = FALSE; |
| 336 // Ensure size is valid and represents what we've been passed. |
| 337 monitor_info->cbSize = buffer->Size(); |
| 338 HMONITOR monitor_handle = static_cast<HMONITOR>(monitor); |
| 339 if (!IsValidMonitorOrDeviceName(monitor_handle, nullptr)) { |
| 340 ipc->return_info.win32_result = ERROR_ACCESS_DENIED; |
| 341 return true; |
| 342 } |
| 343 if (buffer->Size() == sizeof(MONITORINFO) || |
| 344 buffer->Size() == sizeof(MONITORINFOEXW)) |
| 345 success = ::GetMonitorInfoW(monitor_handle, monitor_info); |
| 346 else if (buffer->Size() == sizeof(MONITORINFOEXA)) |
| 347 success = ::GetMonitorInfoA(monitor_handle, monitor_info); |
| 348 ipc->return_info.win32_result = |
| 349 success ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER; |
| 350 return true; |
| 351 } |
| 352 |
| 353 bool ProcessMitigationsWin32KDispatcher:: |
| 354 GetSuggestedOPMProtectedOutputArraySize(IPCInfo* ipc, |
| 355 base::string16* device_name) { |
| 356 if (!policy_base_->GetEnableOPMRedirection()) { |
| 357 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 358 return true; |
| 359 } |
| 360 if (!IsValidMonitorOrDeviceName(nullptr, device_name->c_str())) { |
| 361 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 362 return true; |
| 363 } |
| 364 NTSTATUS status = ProcessMitigationsWin32KLockdownPolicy:: |
| 365 GetSuggestedOPMProtectedOutputArraySizeAction( |
| 366 *ipc->client_info, *device_name, |
| 367 &ipc->return_info.extended[0].unsigned_int); |
| 368 if (!status) { |
| 369 ipc->return_info.extended_count = 1; |
| 370 } |
| 371 ipc->return_info.nt_status = status; |
| 372 return true; |
| 373 } |
| 374 |
| 375 bool ProcessMitigationsWin32KDispatcher::CreateOPMProtectedOutputs( |
| 376 IPCInfo* ipc, |
| 377 base::string16* device_name, |
| 378 CountedBuffer* protected_outputs) { |
| 379 if (!policy_base_->GetEnableOPMRedirection()) { |
| 380 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 381 return true; |
| 382 } |
| 383 if (!IsValidMonitorOrDeviceName(nullptr, device_name->c_str())) { |
| 384 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 385 return true; |
| 386 } |
| 387 uint32_t output_array_size = 0; |
| 388 uint32_t input_array_size = protected_outputs->Size() / sizeof(HANDLE); |
| 389 HANDLE* handles = static_cast<HANDLE*>(protected_outputs->Buffer()); |
| 390 NTSTATUS status = |
| 391 ProcessMitigationsWin32KLockdownPolicy::CreateOPMProtectedOutputsAction( |
| 392 *ipc->client_info, *device_name, handles, input_array_size, |
| 393 &output_array_size); |
| 394 if (!status && (output_array_size <= input_array_size)) { |
| 395 base::AutoLock lock(protected_outputs_lock_); |
| 396 ipc->return_info.extended_count = 1; |
| 397 ipc->return_info.extended[0].unsigned_int = output_array_size; |
| 398 for (uint32_t handle_pos = 0; handle_pos < output_array_size; |
| 399 handle_pos++) { |
| 400 HANDLE handle = handles[handle_pos]; |
| 401 protected_outputs_[handle] = new ProtectedVideoOutput(handle); |
| 402 } |
| 403 } |
| 404 ipc->return_info.nt_status = status; |
| 405 return true; |
| 406 } |
| 407 |
| 408 bool ProcessMitigationsWin32KDispatcher::GetCertificateSize( |
| 409 IPCInfo* ipc, |
| 410 base::string16* device_name) { |
| 411 if (!policy_base_->GetEnableOPMRedirection()) { |
| 412 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 413 return true; |
| 414 } |
| 415 if (!IsValidMonitorOrDeviceName(nullptr, device_name->c_str())) { |
| 416 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 417 return true; |
| 418 } |
| 419 NTSTATUS status = |
| 420 ProcessMitigationsWin32KLockdownPolicy::GetCertificateSizeAction( |
| 421 *ipc->client_info, *device_name, |
| 422 &ipc->return_info.extended[0].unsigned_int); |
| 423 if (!status) { |
| 424 ipc->return_info.extended_count = 1; |
| 425 } |
| 426 ipc->return_info.nt_status = status; |
| 427 return true; |
| 428 } |
| 429 |
| 430 bool ProcessMitigationsWin32KDispatcher::GetCertificate( |
| 431 IPCInfo* ipc, |
| 432 base::string16* device_name, |
| 433 void* shared_buffer_handle, |
| 434 uint32_t shared_buffer_size) { |
| 435 if (!policy_base_->GetEnableOPMRedirection()) { |
| 436 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 437 return true; |
| 438 } |
| 439 if (!IsValidMonitorOrDeviceName(nullptr, device_name->c_str())) { |
| 440 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 441 return true; |
| 442 } |
| 443 // Don't let caller map an arbitrarily large buffer into memory. |
| 444 if (shared_buffer_size > kProtectedVideoOutputSectionSize) { |
| 445 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 446 return true; |
| 447 } |
| 448 base::SharedMemoryHandle handle = |
| 449 GetSharedMemoryHandle(*ipc->client_info, shared_buffer_handle); |
| 450 if (!handle.IsValid()) { |
| 451 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 452 return true; |
| 453 } |
| 454 base::SharedMemory cert_data(handle, false); |
| 455 if (!cert_data.Map(shared_buffer_size)) { |
| 456 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 457 return true; |
| 458 } |
| 459 NTSTATUS status = |
| 460 ProcessMitigationsWin32KLockdownPolicy::GetCertificateAction( |
| 461 *ipc->client_info, *device_name, |
| 462 static_cast<BYTE*>(cert_data.memory()), shared_buffer_size); |
| 463 ipc->return_info.nt_status = status; |
| 464 return true; |
| 465 } |
| 466 |
| 467 bool ProcessMitigationsWin32KDispatcher::DestroyOPMProtectedOutput( |
| 468 IPCInfo* ipc, |
| 469 void* protected_output) { |
| 470 if (!policy_base_->GetEnableOPMRedirection()) { |
| 471 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 472 return true; |
| 473 } |
| 474 scoped_refptr<ProtectedVideoOutput> output = |
| 475 GetProtectedVideoOutput(protected_output, true); |
| 476 NTSTATUS status = STATUS_INVALID_HANDLE; |
| 477 if (output) |
| 478 status = STATUS_SUCCESS; |
| 479 ipc->return_info.nt_status = status; |
| 480 return true; |
| 481 } |
| 482 |
| 483 bool ProcessMitigationsWin32KDispatcher::GetOPMRandomNumber( |
| 484 IPCInfo* ipc, |
| 485 void* protected_output, |
| 486 CountedBuffer* random_number) { |
| 487 if (!policy_base_->GetEnableOPMRedirection()) { |
| 488 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 489 return true; |
| 490 } |
| 491 scoped_refptr<ProtectedVideoOutput> output = |
| 492 GetProtectedVideoOutput(protected_output, false); |
| 493 NTSTATUS status = STATUS_INVALID_PARAMETER; |
| 494 if (!output || random_number->Size() != sizeof(DXGKMDT_OPM_RANDOM_NUMBER)) { |
| 495 status = STATUS_INVALID_PARAMETER; |
| 496 } else { |
| 497 status = ProcessMitigationsWin32KLockdownPolicy::GetOPMRandomNumberAction( |
| 498 *ipc->client_info, output.get()->handle(), random_number->Buffer()); |
| 499 } |
| 500 ipc->return_info.nt_status = status; |
| 501 return true; |
| 502 } |
| 503 |
| 504 bool ProcessMitigationsWin32KDispatcher::SetOPMSigningKeyAndSequenceNumbers( |
| 505 IPCInfo* ipc, |
| 506 void* protected_output, |
| 507 CountedBuffer* parameters) { |
| 508 if (!policy_base_->GetEnableOPMRedirection()) { |
| 509 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 510 return true; |
| 511 } |
| 512 scoped_refptr<ProtectedVideoOutput> output = |
| 513 GetProtectedVideoOutput(protected_output, false); |
| 514 NTSTATUS status = STATUS_INVALID_PARAMETER; |
| 515 if (!output || |
| 516 parameters->Size() != sizeof(DXGKMDT_OPM_ENCRYPTED_PARAMETERS)) { |
| 517 status = STATUS_INVALID_PARAMETER; |
| 518 } else { |
| 519 status = ProcessMitigationsWin32KLockdownPolicy:: |
| 520 SetOPMSigningKeyAndSequenceNumbersAction( |
| 521 *ipc->client_info, output.get()->handle(), parameters->Buffer()); |
| 522 } |
| 523 ipc->return_info.nt_status = status; |
| 524 return true; |
| 525 } |
| 526 |
| 527 bool ProcessMitigationsWin32KDispatcher::ConfigureOPMProtectedOutput( |
| 528 IPCInfo* ipc, |
| 529 void* protected_output, |
| 530 void* shared_buffer_handle) { |
| 531 if (!policy_base_->GetEnableOPMRedirection()) { |
| 532 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 533 return true; |
| 534 } |
| 535 scoped_refptr<ProtectedVideoOutput> output = |
| 536 GetProtectedVideoOutput(protected_output, false); |
| 537 if (!output) { |
| 538 ipc->return_info.nt_status = STATUS_INVALID_HANDLE; |
| 539 return true; |
| 540 }; |
| 541 base::SharedMemoryHandle handle = |
| 542 GetSharedMemoryHandle(*ipc->client_info, shared_buffer_handle); |
| 543 if (!handle.IsValid()) { |
| 544 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 545 return true; |
| 546 } |
| 547 base::SharedMemory buffer(handle, false); |
| 548 if (!buffer.Map(sizeof(DXGKMDT_OPM_CONFIGURE_PARAMETERS))) { |
| 549 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 550 return true; |
| 551 } |
| 552 NTSTATUS status = |
| 553 ProcessMitigationsWin32KLockdownPolicy::ConfigureOPMProtectedOutputAction( |
| 554 *ipc->client_info, output.get()->handle(), buffer.memory()); |
| 555 ipc->return_info.nt_status = status; |
| 556 return true; |
| 557 } |
| 558 |
| 559 bool ProcessMitigationsWin32KDispatcher::GetOPMInformation( |
| 560 IPCInfo* ipc, |
| 561 void* protected_output, |
| 562 void* shared_buffer_handle) { |
| 563 if (!policy_base_->GetEnableOPMRedirection()) { |
| 564 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 565 return true; |
| 566 } |
| 567 scoped_refptr<ProtectedVideoOutput> output = |
| 568 GetProtectedVideoOutput(protected_output, false); |
| 569 if (!output) { |
| 570 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 571 return true; |
| 572 } |
| 573 base::SharedMemoryHandle handle = |
| 574 GetSharedMemoryHandle(*ipc->client_info, shared_buffer_handle); |
| 575 if (!handle.IsValid()) { |
| 576 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 577 return true; |
| 578 } |
| 579 base::SharedMemory buffer(handle, false); |
| 580 |
| 581 size_t shared_buffer_size = |
| 582 std::max(sizeof(DXGKMDT_OPM_GET_INFO_PARAMETERS), |
| 583 sizeof(DXGKMDT_OPM_REQUESTED_INFORMATION)); |
| 584 if (!buffer.Map(shared_buffer_size)) { |
| 585 ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
| 586 return true; |
| 587 } |
| 588 DXGKMDT_OPM_REQUESTED_INFORMATION requested_info = {}; |
| 589 NTSTATUS status = |
| 590 ProcessMitigationsWin32KLockdownPolicy::GetOPMInformationAction( |
| 591 *ipc->client_info, output.get()->handle(), buffer.memory(), |
| 592 &requested_info); |
| 593 if (!status) { |
| 594 memcpy(buffer.memory(), &requested_info, |
| 595 sizeof(DXGKMDT_OPM_REQUESTED_INFORMATION)); |
| 596 } |
| 597 ipc->return_info.nt_status = status; |
| 598 return true; |
| 599 } |
| 600 |
56 } // namespace sandbox | 601 } // namespace sandbox |
57 | 602 |
OLD | NEW |