Index: sandbox/win/src/process_mitigations_win32k_dispatcher.cc |
diff --git a/sandbox/win/src/process_mitigations_win32k_dispatcher.cc b/sandbox/win/src/process_mitigations_win32k_dispatcher.cc |
index e426084f861abdd9387d5578187365ff17720fad..36db4267e0f3f50bb0fc5ac8ef94180c8f8f2440 100644 |
--- a/sandbox/win/src/process_mitigations_win32k_dispatcher.cc |
+++ b/sandbox/win/src/process_mitigations_win32k_dispatcher.cc |
@@ -3,18 +3,123 @@ |
// found in the LICENSE file. |
#include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" |
+ |
+#include <algorithm> |
+ |
+#include "base/memory/shared_memory.h" |
+#include "base/strings/string16.h" |
+#include "base/win/windows_version.h" |
#include "sandbox/win/src/interception.h" |
#include "sandbox/win/src/interceptors.h" |
#include "sandbox/win/src/ipc_tags.h" |
#include "sandbox/win/src/process_mitigations_win32k_interception.h" |
+#include "sandbox/win/src/process_mitigations_win32k_policy.h" |
namespace sandbox { |
+namespace { |
+ |
+base::SharedMemoryHandle GetSharedMemoryHandle(const ClientInfo& client_info, |
+ HANDLE handle) { |
+ HANDLE result_handle = nullptr; |
+ intptr_t handle_int = reinterpret_cast<intptr_t>(handle); |
+ if (handle_int <= 0 || |
+ !::DuplicateHandle(client_info.process, handle, ::GetCurrentProcess(), |
+ &result_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { |
+ result_handle = nullptr; |
+ } |
+ return base::SharedMemoryHandle(result_handle, ::GetCurrentProcessId()); |
+} |
+ |
+} // namespace |
+ |
+ProtectedVideoOutput::~ProtectedVideoOutput() { |
+ ProcessMitigationsWin32KLockdownPolicy::DestroyOPMProtectedOutputAction( |
+ handle_); |
+} |
+ |
+scoped_refptr<ProtectedVideoOutput> |
+ProcessMitigationsWin32KDispatcher::GetProtectedVideoOutput( |
+ HANDLE handle, |
+ bool destroy_output) { |
+ base::AutoLock lock(protected_outputs_lock_); |
+ scoped_refptr<ProtectedVideoOutput> result; |
+ auto it = protected_outputs_.find(handle); |
+ if (it != protected_outputs_.end()) { |
+ result = it->second; |
+ if (destroy_output) |
+ protected_outputs_.erase(it); |
+ } |
+ return result; |
+} |
+ |
ProcessMitigationsWin32KDispatcher::ProcessMitigationsWin32KDispatcher( |
PolicyBase* policy_base) |
: policy_base_(policy_base) { |
+ static const IPCCall enum_display_monitors_params = { |
+ {IPC_USER_ENUMDISPLAYMONITORS_TAG, {INOUTPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::EnumDisplayMonitors)}; |
+ static const IPCCall get_monitor_info_params = { |
+ {IPC_USER_GETMONITORINFO_TAG, {VOIDPTR_TYPE, INOUTPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::GetMonitorInfo)}; |
+ static const IPCCall get_suggested_output_size_params = { |
+ {IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG, {WCHAR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher:: |
+ GetSuggestedOPMProtectedOutputArraySize)}; |
+ static const IPCCall create_protected_outputs_params = { |
+ {IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG, {WCHAR_TYPE, INOUTPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::CreateOPMProtectedOutputs)}; |
+ static const IPCCall get_cert_size_params = { |
+ {IPC_GDI_GETCERTIFICATESIZE_TAG, {WCHAR_TYPE, VOIDPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::GetCertificateSize)}; |
+ static const IPCCall get_cert_params = { |
+ {IPC_GDI_GETCERTIFICATE_TAG, |
+ {WCHAR_TYPE, VOIDPTR_TYPE, VOIDPTR_TYPE, UINT32_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::GetCertificate)}; |
+ static const IPCCall destroy_protected_output_params = { |
+ {IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG, {VOIDPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::DestroyOPMProtectedOutput)}; |
+ static const IPCCall get_random_number_params = { |
+ {IPC_GDI_GETOPMRANDOMNUMBER_TAG, {VOIDPTR_TYPE, INOUTPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::GetOPMRandomNumber)}; |
+ static const IPCCall set_signing_key_params = { |
+ {IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG, |
+ {VOIDPTR_TYPE, INOUTPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher:: |
+ SetOPMSigningKeyAndSequenceNumbers)}; |
+ static const IPCCall configure_protected_output_params = { |
+ {IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG, {VOIDPTR_TYPE, VOIDPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::ConfigureOPMProtectedOutput)}; |
+ static const IPCCall get_information_params = { |
+ {IPC_GDI_GETOPMINFORMATION_TAG, {VOIDPTR_TYPE, VOIDPTR_TYPE}}, |
+ reinterpret_cast<CallbackGeneric>( |
+ &ProcessMitigationsWin32KDispatcher::GetOPMInformation)}; |
+ |
+ ipc_calls_.push_back(enum_display_monitors_params); |
+ ipc_calls_.push_back(get_monitor_info_params); |
+ ipc_calls_.push_back(get_suggested_output_size_params); |
+ ipc_calls_.push_back(create_protected_outputs_params); |
+ ipc_calls_.push_back(get_cert_size_params); |
+ ipc_calls_.push_back(get_cert_params); |
+ ipc_calls_.push_back(destroy_protected_output_params); |
+ ipc_calls_.push_back(get_random_number_params); |
+ ipc_calls_.push_back(set_signing_key_params); |
+ ipc_calls_.push_back(configure_protected_output_params); |
+ ipc_calls_.push_back(get_information_params); |
} |
+ProcessMitigationsWin32KDispatcher::~ProcessMitigationsWin32KDispatcher() {} |
+ |
bool ProcessMitigationsWin32KDispatcher::SetupService( |
InterceptionManager* manager, int service) { |
if (!(policy_base_->GetProcessMitigations() & |
@@ -47,11 +152,426 @@ bool ProcessMitigationsWin32KDispatcher::SetupService( |
return true; |
} |
+ case IPC_USER_ENUMDISPLAYMONITORS_TAG: { |
+ if (!INTERCEPT_EAT(manager, L"user32.dll", EnumDisplayMonitors, |
+ ENUMDISPLAYMONITORS_ID, 20)) { |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ case IPC_USER_ENUMDISPLAYDEVICES_TAG: { |
+ if (!INTERCEPT_EAT(manager, L"user32.dll", EnumDisplayDevicesA, |
+ ENUMDISPLAYDEVICESA_ID, 20)) { |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ case IPC_USER_GETMONITORINFO_TAG: { |
+ if (!INTERCEPT_EAT(manager, L"user32.dll", GetMonitorInfoA, |
+ GETMONITORINFOA_ID, 12)) { |
+ return false; |
+ } |
+ |
+ if (!INTERCEPT_EAT(manager, L"user32.dll", GetMonitorInfoW, |
+ GETMONITORINFOW_ID, 12)) { |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ case IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", CreateOPMProtectedOutputs, |
+ CREATEOPMPROTECTEDOUTPUTS_ID, 24)) { |
+ return false; |
+ } |
+ return true; |
+ |
+ case IPC_GDI_GETCERTIFICATE_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetCertificate, |
+ GETCERTIFICATE_ID, 20)) { |
+ return false; |
+ } |
+ if (base::win::GetVersion() < base::win::VERSION_WIN10) |
+ return true; |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetCertificateByHandle, |
+ GETCERTIFICATEBYHANDLE_ID, 20)) { |
+ return false; |
+ } |
+ return true; |
+ |
+ case IPC_GDI_GETCERTIFICATESIZE_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetCertificateSize, |
+ GETCERTIFICATESIZE_ID, 16)) { |
+ return false; |
+ } |
+ if (base::win::GetVersion() < base::win::VERSION_WIN10) |
+ return true; |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetCertificateSizeByHandle, |
+ GETCERTIFICATESIZEBYHANDLE_ID, 16)) { |
+ return false; |
+ } |
+ return true; |
+ |
+ case IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", DestroyOPMProtectedOutput, |
+ DESTROYOPMPROTECTEDOUTPUT_ID, 8)) { |
+ return false; |
+ } |
+ return true; |
+ |
+ case IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", ConfigureOPMProtectedOutput, |
+ CONFIGUREOPMPROTECTEDOUTPUT_ID, 20)) { |
+ return false; |
+ } |
+ return true; |
+ |
+ case IPC_GDI_GETOPMINFORMATION_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetOPMInformation, |
+ GETOPMINFORMATION_ID, 16)) { |
+ return false; |
+ } |
+ return true; |
+ |
+ case IPC_GDI_GETOPMRANDOMNUMBER_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", GetOPMRandomNumber, |
+ GETOPMRANDOMNUMBER_ID, 12)) { |
+ return false; |
+ } |
+ return true; |
+ |
+ case IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", |
+ GetSuggestedOPMProtectedOutputArraySize, |
+ GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_ID, 12)) { |
+ return false; |
+ } |
+ return true; |
+ |
+ case IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG: |
+ if (!INTERCEPT_EAT(manager, L"gdi32.dll", |
+ SetOPMSigningKeyAndSequenceNumbers, |
+ SETOPMSIGNINGKEYANDSEQUENCENUMBERS_ID, 12)) { |
+ return false; |
+ } |
+ return true; |
+ |
default: |
break; |
} |
return false; |
} |
+bool ProcessMitigationsWin32KDispatcher::EnumDisplayMonitors( |
+ IPCInfo* ipc, |
+ CountedBuffer* buffer) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.win32_result = ERROR_ACCESS_DENIED; |
+ return true; |
+ } |
+ |
+ if (buffer->Size() != sizeof(EnumMonitorsResult)) { |
+ ipc->return_info.win32_result = ERROR_INVALID_PARAMETER; |
+ return true; |
+ } |
+ HMONITOR monitor_list[kMaxEnumMonitors] = {}; |
+ |
+ uint32_t monitor_list_count = |
+ ProcessMitigationsWin32KLockdownPolicy::EnumDisplayMonitorsAction( |
+ *ipc->client_info, monitor_list, kMaxEnumMonitors); |
+ DCHECK(monitor_list_count <= kMaxEnumMonitors); |
+ |
+ EnumMonitorsResult* result = |
+ static_cast<EnumMonitorsResult*>(buffer->Buffer()); |
+ for (uint32_t monitor_pos = 0; monitor_pos < monitor_list_count; |
+ ++monitor_pos) { |
+ result->monitors[monitor_pos] = monitor_list[monitor_pos]; |
+ } |
+ result->monitor_count = monitor_list_count; |
+ ipc->return_info.win32_result = 0; |
+ |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::GetMonitorInfo(IPCInfo* ipc, |
+ void* monitor, |
+ CountedBuffer* buffer) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.win32_result = ERROR_ACCESS_DENIED; |
+ return true; |
+ } |
+ if (buffer->Size() != sizeof(MONITORINFOEXW)) { |
+ ipc->return_info.win32_result = ERROR_INVALID_PARAMETER; |
+ return true; |
+ } |
+ MONITORINFO* monitor_info = static_cast<MONITORINFO*>(buffer->Buffer()); |
+ // Ensure size is valid and represents what we've been passed. |
+ monitor_info->cbSize = buffer->Size(); |
+ HMONITOR monitor_handle = static_cast<HMONITOR>(monitor); |
+ BOOL success = ProcessMitigationsWin32KLockdownPolicy::GetMonitorInfoAction( |
+ *ipc->client_info, monitor_handle, monitor_info); |
+ ipc->return_info.win32_result = |
+ success ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher:: |
+ GetSuggestedOPMProtectedOutputArraySize(IPCInfo* ipc, |
+ base::string16* device_name) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ NTSTATUS status = ProcessMitigationsWin32KLockdownPolicy:: |
+ GetSuggestedOPMProtectedOutputArraySizeAction( |
+ *ipc->client_info, *device_name, |
+ &ipc->return_info.extended[0].unsigned_int); |
+ if (!status) { |
+ ipc->return_info.extended_count = 1; |
+ } |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::CreateOPMProtectedOutputs( |
+ IPCInfo* ipc, |
+ base::string16* device_name, |
+ CountedBuffer* protected_outputs) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ uint32_t output_array_size = 0; |
+ uint32_t input_array_size = protected_outputs->Size() / sizeof(HANDLE); |
+ HANDLE* handles = static_cast<HANDLE*>(protected_outputs->Buffer()); |
+ NTSTATUS status = |
+ ProcessMitigationsWin32KLockdownPolicy::CreateOPMProtectedOutputsAction( |
+ *ipc->client_info, *device_name, handles, input_array_size, |
+ &output_array_size); |
+ if (!status && (output_array_size <= input_array_size)) { |
+ base::AutoLock lock(protected_outputs_lock_); |
+ ipc->return_info.extended_count = 1; |
+ ipc->return_info.extended[0].unsigned_int = output_array_size; |
+ for (uint32_t handle_pos = 0; handle_pos < output_array_size; |
+ handle_pos++) { |
+ HANDLE handle = handles[handle_pos]; |
+ protected_outputs_[handle] = new ProtectedVideoOutput(handle); |
+ } |
+ } |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::GetCertificateSize( |
+ IPCInfo* ipc, |
+ base::string16* device_name, |
+ void* protected_output) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ NTSTATUS status = STATUS_INVALID_PARAMETER; |
+ if (device_name->size() > 0) { |
+ status = ProcessMitigationsWin32KLockdownPolicy::GetCertificateSizeAction( |
+ *ipc->client_info, *device_name, |
+ &ipc->return_info.extended[0].unsigned_int); |
+ } else { |
+ scoped_refptr<ProtectedVideoOutput> output = |
+ GetProtectedVideoOutput(protected_output, false); |
+ if (output) { |
+ status = ProcessMitigationsWin32KLockdownPolicy:: |
+ GetCertificateSizeByHandleAction( |
+ *ipc->client_info, output.get()->handle(), |
+ &ipc->return_info.extended[0].unsigned_int); |
+ } |
+ } |
+ if (!status) { |
+ ipc->return_info.extended_count = 1; |
+ } |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::GetCertificate( |
+ IPCInfo* ipc, |
+ base::string16* device_name, |
+ void* protected_output, |
+ void* shared_buffer_handle, |
+ uint32_t shared_buffer_size) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ // Don't let caller map an arbitrarily large buffer into memory. |
+ if (shared_buffer_size > kProtectedVideoOutputSectionSize) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ base::SharedMemoryHandle handle = |
+ GetSharedMemoryHandle(*ipc->client_info, shared_buffer_handle); |
+ if (!handle.IsValid()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ base::SharedMemory cert_data(handle, false); |
+ if (!cert_data.Map(shared_buffer_size)) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ NTSTATUS status = STATUS_INVALID_PARAMETER; |
+ if (device_name->size() > 0) { |
+ status = ProcessMitigationsWin32KLockdownPolicy::GetCertificateAction( |
+ *ipc->client_info, *device_name, static_cast<BYTE*>(cert_data.memory()), |
+ shared_buffer_size); |
+ } else { |
+ scoped_refptr<ProtectedVideoOutput> output = |
+ GetProtectedVideoOutput(protected_output, false); |
+ if (output) { |
+ status = |
+ ProcessMitigationsWin32KLockdownPolicy::GetCertificateByHandleAction( |
+ *ipc->client_info, output.get()->handle(), |
+ static_cast<BYTE*>(cert_data.memory()), shared_buffer_size); |
+ } |
+ } |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::DestroyOPMProtectedOutput( |
+ IPCInfo* ipc, |
+ void* protected_output) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ scoped_refptr<ProtectedVideoOutput> output = |
+ GetProtectedVideoOutput(protected_output, true); |
+ NTSTATUS status = STATUS_INVALID_HANDLE; |
+ if (output) |
+ status = STATUS_SUCCESS; |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::GetOPMRandomNumber( |
+ IPCInfo* ipc, |
+ void* protected_output, |
+ CountedBuffer* random_number) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ scoped_refptr<ProtectedVideoOutput> output = |
+ GetProtectedVideoOutput(protected_output, false); |
+ NTSTATUS status = STATUS_INVALID_PARAMETER; |
+ if (!output || random_number->Size() != sizeof(DXGKMDT_OPM_RANDOM_NUMBER)) { |
+ status = STATUS_INVALID_PARAMETER; |
+ } else { |
+ status = ProcessMitigationsWin32KLockdownPolicy::GetOPMRandomNumberAction( |
+ *ipc->client_info, output.get()->handle(), random_number->Buffer()); |
+ } |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::SetOPMSigningKeyAndSequenceNumbers( |
+ IPCInfo* ipc, |
+ void* protected_output, |
+ CountedBuffer* parameters) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ scoped_refptr<ProtectedVideoOutput> output = |
+ GetProtectedVideoOutput(protected_output, false); |
+ NTSTATUS status = STATUS_INVALID_PARAMETER; |
+ if (!output || |
+ parameters->Size() != sizeof(DXGKMDT_OPM_ENCRYPTED_PARAMETERS)) { |
+ status = STATUS_INVALID_PARAMETER; |
+ } else { |
+ status = ProcessMitigationsWin32KLockdownPolicy:: |
+ SetOPMSigningKeyAndSequenceNumbersAction( |
+ *ipc->client_info, output.get()->handle(), parameters->Buffer()); |
+ } |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::ConfigureOPMProtectedOutput( |
+ IPCInfo* ipc, |
+ void* protected_output, |
+ void* shared_buffer_handle) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ scoped_refptr<ProtectedVideoOutput> output = |
+ GetProtectedVideoOutput(protected_output, false); |
+ if (!output) { |
+ ipc->return_info.nt_status = STATUS_INVALID_HANDLE; |
+ return true; |
+ }; |
+ base::SharedMemoryHandle handle = |
+ GetSharedMemoryHandle(*ipc->client_info, shared_buffer_handle); |
+ if (!handle.IsValid()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ base::SharedMemory buffer(handle, false); |
+ if (!buffer.Map(sizeof(DXGKMDT_OPM_CONFIGURE_PARAMETERS))) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ NTSTATUS status = |
+ ProcessMitigationsWin32KLockdownPolicy::ConfigureOPMProtectedOutputAction( |
+ *ipc->client_info, output.get()->handle(), buffer.memory()); |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
+bool ProcessMitigationsWin32KDispatcher::GetOPMInformation( |
+ IPCInfo* ipc, |
+ void* protected_output, |
+ void* shared_buffer_handle) { |
+ if (!policy_base_->GetEnableOPMRedirection()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ scoped_refptr<ProtectedVideoOutput> output = |
+ GetProtectedVideoOutput(protected_output, false); |
+ if (!output) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ base::SharedMemoryHandle handle = |
+ GetSharedMemoryHandle(*ipc->client_info, shared_buffer_handle); |
+ if (!handle.IsValid()) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ base::SharedMemory buffer(handle, false); |
+ |
+ size_t shared_buffer_size = |
+ std::max(sizeof(DXGKMDT_OPM_GET_INFO_PARAMETERS), |
+ sizeof(DXGKMDT_OPM_REQUESTED_INFORMATION)); |
+ if (!buffer.Map(shared_buffer_size)) { |
+ ipc->return_info.nt_status = STATUS_ACCESS_DENIED; |
+ return true; |
+ } |
+ DXGKMDT_OPM_REQUESTED_INFORMATION requested_info = {}; |
+ NTSTATUS status = |
+ ProcessMitigationsWin32KLockdownPolicy::GetOPMInformationAction( |
+ *ipc->client_info, output.get()->handle(), buffer.memory(), |
+ &requested_info); |
+ if (!status) { |
+ memcpy(buffer.memory(), &requested_info, |
+ sizeof(DXGKMDT_OPM_REQUESTED_INFORMATION)); |
+ } |
+ ipc->return_info.nt_status = status; |
+ return true; |
+} |
+ |
} // namespace sandbox |