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