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

Side by Side Diff: sandbox/win/src/process_mitigations_win32k_interception.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, 7 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 unified diff | Download patch
OLDNEW
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_interception.h" 5 #include "sandbox/win/src/process_mitigations_win32k_interception.h"
6 6
7 #include <algorithm>
8
9 #include "base/numerics/safe_conversions.h"
10 #include "base/numerics/safe_math.h"
11 #include "base/win/scoped_handle.h"
12 #include "sandbox/win/src/crosscall_client.h"
13 #include "sandbox/win/src/ipc_tags.h"
14 #include "sandbox/win/src/policy_params.h"
15 #include "sandbox/win/src/policy_target.h"
16 #include "sandbox/win/src/sandbox_factory.h"
17 #include "sandbox/win/src/sandbox_nt_util.h"
18 #include "sandbox/win/src/sharedmem_ipc_client.h"
19 #include "sandbox/win/src/target_services.h"
20
7 namespace sandbox { 21 namespace sandbox {
8 22
23 namespace {
24
25 // Implement a simple shared memory class as we can't use the base one.
26 class ScopedSharedMemory {
27 public:
28 ScopedSharedMemory(uint32_t size) : memory_(nullptr) {
29 handle_.Set(::CreateFileMapping(INVALID_HANDLE_VALUE, nullptr,
30 PAGE_READWRITE | SEC_COMMIT, 0, size,
31 nullptr));
32 if (handle_.IsValid()) {
33 memory_ = ::MapViewOfFile(handle_.Get(), FILE_MAP_READ | FILE_MAP_WRITE,
34 0, 0, size);
35 }
36 }
37 ~ScopedSharedMemory() {
38 if (memory_)
39 ::UnmapViewOfFile(memory_);
40 }
41
42 void* handle() { return handle_.Get(); }
43 void* memory() { return memory_; }
44 bool IsValid() { return handle_.IsValid() && memory_; }
45
46 private:
47 base::win::ScopedHandle handle_;
48 void* memory_;
49 };
50
51 void UnicodeStringToString(PUNICODE_STRING unicode_string,
52 base::string16* result) {
53 *result = base::string16(
54 unicode_string->Buffer,
55 unicode_string->Buffer +
56 (unicode_string->Length / sizeof(unicode_string->Buffer[0])));
57 }
58
59 } // namespace
60
9 BOOL WINAPI TargetGdiDllInitialize( 61 BOOL WINAPI TargetGdiDllInitialize(
10 GdiDllInitializeFunction orig_gdi_dll_initialize, 62 GdiDllInitializeFunction orig_gdi_dll_initialize,
11 HANDLE dll, 63 HANDLE dll,
12 DWORD reason) { 64 DWORD reason) {
13 return TRUE; 65 return TRUE;
14 } 66 }
15 67
16 HGDIOBJ WINAPI TargetGetStockObject( 68 HGDIOBJ WINAPI TargetGetStockObject(
17 GetStockObjectFunction orig_get_stock_object, 69 GetStockObjectFunction orig_get_stock_object,
18 int object) { 70 int object) {
19 return reinterpret_cast<HGDIOBJ>(NULL); 71 return reinterpret_cast<HGDIOBJ>(NULL);
20 } 72 }
21 73
22 ATOM WINAPI TargetRegisterClassW( 74 ATOM WINAPI TargetRegisterClassW(
23 RegisterClassWFunction orig_register_class_function, 75 RegisterClassWFunction orig_register_class_function,
24 const WNDCLASS* wnd_class) { 76 const WNDCLASS* wnd_class) {
25 return TRUE; 77 return TRUE;
26 } 78 }
27 79
80 BOOL WINAPI TargetEnumDisplayMonitors(EnumDisplayMonitorsFunction,
81 HDC hdc,
82 LPCRECT lprcClip,
83 MONITORENUMPROC lpfnEnum,
84 LPARAM dwData) {
85 if (!lpfnEnum || hdc || lprcClip) {
86 return FALSE;
87 }
88
89 // We don't trust that the IPC can work this early.
90 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
91 return FALSE;
92
93 void* ipc_memory = GetGlobalIPCMemory();
94 if (ipc_memory == NULL)
95 return FALSE;
96
97 CrossCallReturn answer = {0};
98 answer.nt_status = 0;
99 EnumMonitorsResult result = {};
100 InOutCountedBuffer result_buffer(&result, sizeof(result));
101 SharedMemIPCClient ipc(ipc_memory);
102 ResultCode code =
103 CrossCall(ipc, IPC_USER_ENUMDISPLAYMONITORS_TAG, result_buffer, &answer);
104
105 if (code != SBOX_ALL_OK) {
106 return FALSE;
107 }
108
109 if (answer.win32_result) {
110 return FALSE;
111 }
112
113 if (result.monitor_count > kMaxEnumMonitors) {
114 return FALSE;
115 }
116
117 for (uint32_t monitor_pos = 0; monitor_pos < result.monitor_count;
118 ++monitor_pos) {
119 BOOL continue_enum =
120 lpfnEnum(result.monitors[monitor_pos], nullptr, nullptr, dwData);
121 if (!continue_enum)
122 return FALSE;
123 }
124
125 return TRUE;
126 }
127
128 BOOL WINAPI TargetEnumDisplayDevicesA(EnumDisplayDevicesAFunction,
129 LPCSTR lpDevice,
130 DWORD iDevNum,
131 PDISPLAY_DEVICEA lpDisplayDevice,
132 DWORD dwFlags) {
133 return FALSE;
134 }
135
136 static BOOL CallMonitorInfo(HMONITOR monitor,
137 MONITORINFOEXW* monitor_info_ptr) {
138 // We don't trust that the IPC can work this early.
139 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
140 return FALSE;
141
142 void* ipc_memory = GetGlobalIPCMemory();
143 if (ipc_memory == NULL)
144 return FALSE;
145
146 CrossCallReturn answer = {};
147 SharedMemIPCClient ipc(ipc_memory);
148 InOutCountedBuffer buffer(monitor_info_ptr, sizeof(*monitor_info_ptr));
149 ResultCode code = CrossCall(ipc, IPC_USER_GETMONITORINFO_TAG,
150 static_cast<void*>(monitor), buffer, &answer);
151
152 if (code != SBOX_ALL_OK) {
153 return FALSE;
154 }
155
156 if (answer.win32_result != ERROR_SUCCESS)
157 return FALSE;
158
159 return TRUE;
160 }
161
162 BOOL WINAPI TargetGetMonitorInfoA(GetMonitorInfoAFunction,
163 HMONITOR monitor,
164 MONITORINFO* monitor_info_ptr) {
165 if (!monitor_info_ptr)
166 return FALSE;
167 DWORD size = monitor_info_ptr->cbSize;
168 if (size != sizeof(MONITORINFO) && size != sizeof(MONITORINFOEXA)) {
169 return FALSE;
170 }
171 MONITORINFOEXW monitor_info_tmp = {};
172 monitor_info_tmp.cbSize = sizeof(monitor_info_tmp);
173 BOOL success = CallMonitorInfo(monitor, &monitor_info_tmp);
174 if (!success)
175 return FALSE;
176 memcpy(monitor_info_ptr, &monitor_info_tmp, sizeof(*monitor_info_ptr));
177 if (size == sizeof(MONITORINFOEXA)) {
178 MONITORINFOEXA* monitor_info_exa =
179 reinterpret_cast<MONITORINFOEXA*>(monitor_info_ptr);
180 if (!::WideCharToMultiByte(CP_ACP, 0, monitor_info_tmp.szDevice, -1,
181 monitor_info_exa->szDevice,
182 sizeof(monitor_info_exa->szDevice), nullptr,
183 nullptr)) {
184 return FALSE;
185 }
186 }
187 return TRUE;
188 }
189
190 BOOL WINAPI TargetGetMonitorInfoW(GetMonitorInfoWFunction,
191 HMONITOR monitor,
192 LPMONITORINFO monitor_info_ptr) {
193 if (!monitor_info_ptr)
194 return FALSE;
195 DWORD size = monitor_info_ptr->cbSize;
196 if (size != sizeof(MONITORINFO) && size != sizeof(MONITORINFOEXW)) {
197 return FALSE;
198 }
199 MONITORINFOEXW monitor_info_tmp = {};
200 monitor_info_tmp.cbSize = sizeof(monitor_info_tmp);
201 BOOL success = CallMonitorInfo(monitor, &monitor_info_tmp);
202 if (!success)
203 return FALSE;
204 memcpy(monitor_info_ptr, &monitor_info_tmp, size);
205 return TRUE;
206 }
207
208 static NTSTATUS GetCertificateCommon(
209 PUNICODE_STRING device_name,
210 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
211 DXGKMDT_CERTIFICATE_TYPE certificate_type,
212 BYTE* certificate,
213 ULONG certificate_size) {
214 // Don't support arbitrarily large certificate buffers.
215 if (certificate_size > kProtectedVideoOutputSectionSize)
216 return STATUS_INVALID_PARAMETER;
217 if (certificate_type != DXGKMDT_OPM_CERTIFICATE)
218 return STATUS_INVALID_PARAMETER;
219 if (device_name && device_name->Length == 0)
220 return STATUS_INVALID_PARAMETER;
221 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
222 return STATUS_ACCESS_DENIED;
223 void* ipc_memory = GetGlobalIPCMemory();
224 if (ipc_memory == NULL)
225 return STATUS_ACCESS_DENIED;
226
227 ScopedSharedMemory buffer(certificate_size);
228 if (!buffer.IsValid())
229 return STATUS_INVALID_PARAMETER;
230 base::string16 device_name_str;
231 void* protected_output_handle = nullptr;
232 if (device_name) {
233 if (device_name->Length == 0)
234 return STATUS_INVALID_PARAMETER;
235 UnicodeStringToString(device_name, &device_name_str);
236 } else {
237 protected_output_handle = protected_output;
238 }
239 CrossCallReturn answer = {};
240 SharedMemIPCClient ipc(ipc_memory);
241 ResultCode code =
242 CrossCall(ipc, IPC_GDI_GETCERTIFICATE_TAG, device_name_str.c_str(),
243 protected_output_handle, buffer.handle(),
244 static_cast<uint32_t>(certificate_size), &answer);
245
246 if (code != SBOX_ALL_OK) {
247 return STATUS_ACCESS_DENIED;
248 }
249
250 if (!answer.nt_status)
251 memcpy(certificate, buffer.memory(), certificate_size);
252
253 return answer.nt_status;
254 }
255
256 NTSTATUS WINAPI TargetGetCertificate(GetCertificateFunction,
257 PUNICODE_STRING device_name,
258 DXGKMDT_CERTIFICATE_TYPE certificate_type,
259 BYTE* certificate,
260 ULONG certificate_size) {
261 return GetCertificateCommon(device_name, nullptr, certificate_type,
262 certificate, certificate_size);
263 }
264
265 static NTSTATUS GetCertificateSizeCommon(
266 PUNICODE_STRING device_name,
267 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
268 DXGKMDT_CERTIFICATE_TYPE certificate_type,
269 ULONG* certificate_length) {
270 if (certificate_type != DXGKMDT_OPM_CERTIFICATE)
271 return STATUS_INVALID_PARAMETER;
272 if (device_name && device_name->Length == 0)
273 return STATUS_INVALID_PARAMETER;
274 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
275 return STATUS_ACCESS_DENIED;
276 void* ipc_memory = GetGlobalIPCMemory();
277 if (ipc_memory == NULL)
278 return STATUS_ACCESS_DENIED;
279
280 CrossCallReturn answer = {};
281 SharedMemIPCClient ipc(ipc_memory);
282 base::string16 device_name_str;
283 void* protected_output_handle = nullptr;
284 if (device_name) {
285 UnicodeStringToString(device_name, &device_name_str);
286 } else {
287 protected_output_handle = protected_output;
288 }
289 ResultCode code =
290 CrossCall(ipc, IPC_GDI_GETCERTIFICATESIZE_TAG, device_name_str.c_str(),
291 protected_output_handle, &answer);
292
293 if (code != SBOX_ALL_OK) {
294 return STATUS_ACCESS_DENIED;
295 }
296
297 if (!answer.nt_status)
298 *certificate_length = answer.extended[0].unsigned_int;
299
300 return answer.nt_status;
301 }
302
303 NTSTATUS WINAPI
304 TargetGetCertificateSize(GetCertificateSizeFunction,
305 PUNICODE_STRING device_name,
306 DXGKMDT_CERTIFICATE_TYPE certificate_type,
307 ULONG* certificate_length) {
308 return GetCertificateSizeCommon(device_name, nullptr, certificate_type,
309 certificate_length);
310 }
311
312 SANDBOX_INTERCEPT NTSTATUS WINAPI TargetGetCertificateByHandle(
313 GetCertificateByHandleFunction orig_get_certificate_function,
314 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
315 DXGKMDT_CERTIFICATE_TYPE certificate_type,
316 BYTE* certificate,
317 ULONG certificate_length) {
318 return GetCertificateCommon(nullptr, protected_output, certificate_type,
319 certificate, certificate_length);
320 }
321
322 SANDBOX_INTERCEPT NTSTATUS WINAPI TargetGetCertificateSizeByHandle(
323 GetCertificateSizeByHandleFunction orig_get_certificate_size_function,
324 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
325 DXGKMDT_CERTIFICATE_TYPE certificate_type,
326 ULONG* certificate_length) {
327 return GetCertificateSizeCommon(nullptr, protected_output, certificate_type,
328 certificate_length);
329 }
330
331 NTSTATUS WINAPI
332 TargetDestroyOPMProtectedOutput(DestroyOPMProtectedOutputFunction,
333 OPM_PROTECTED_OUTPUT_HANDLE protected_output) {
334 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
335 return STATUS_ACCESS_DENIED;
336 void* ipc_memory = GetGlobalIPCMemory();
337 if (ipc_memory == NULL)
338 return STATUS_ACCESS_DENIED;
339
340 CrossCallReturn answer = {};
341 SharedMemIPCClient ipc(ipc_memory);
342 ResultCode code = CrossCall(ipc, IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG,
343 static_cast<void*>(protected_output), &answer);
344
345 if (code != SBOX_ALL_OK) {
346 return STATUS_ACCESS_DENIED;
347 }
348
349 return answer.nt_status;
350 }
351
352 NTSTATUS WINAPI TargetConfigureOPMProtectedOutput(
353 ConfigureOPMProtectedOutputFunction,
354 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
355 const DXGKMDT_OPM_CONFIGURE_PARAMETERS* parameters,
356 ULONG additional_parameters_size,
357 const BYTE* additional_parameters) {
358 // Don't support additional parameters.
359 if (additional_parameters_size > 0)
360 return STATUS_INVALID_PARAMETER;
361
362 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
363 return STATUS_ACCESS_DENIED;
364 void* ipc_memory = GetGlobalIPCMemory();
365 if (ipc_memory == NULL)
366 return STATUS_ACCESS_DENIED;
367
368 ScopedSharedMemory buffer(sizeof(*parameters));
369 if (!buffer.IsValid())
370 return STATUS_INVALID_PARAMETER;
371 memcpy(buffer.memory(), parameters, sizeof(*parameters));
372 CrossCallReturn answer = {};
373 SharedMemIPCClient ipc(ipc_memory);
374 ResultCode code =
375 CrossCall(ipc, IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG,
376 static_cast<void*>(protected_output), buffer.handle(), &answer);
377
378 if (code != SBOX_ALL_OK) {
379 return STATUS_ACCESS_DENIED;
380 }
381
382 return answer.nt_status;
383 }
384
385 NTSTATUS WINAPI TargetGetOPMInformation(
386 GetOPMInformationFunction,
387 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
388 const DXGKMDT_OPM_GET_INFO_PARAMETERS* parameters,
389 DXGKMDT_OPM_REQUESTED_INFORMATION* requested_information) {
390 size_t max_size =
391 std::max(sizeof(*parameters), sizeof(*requested_information));
392
393 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
394 return STATUS_ACCESS_DENIED;
395 void* ipc_memory = GetGlobalIPCMemory();
396 if (ipc_memory == NULL)
397 return STATUS_ACCESS_DENIED;
398
399 ScopedSharedMemory buffer(base::checked_cast<uint32_t>(max_size));
400 if (!buffer.IsValid())
401 return STATUS_INVALID_PARAMETER;
402 memcpy(buffer.memory(), parameters, sizeof(*parameters));
403 CrossCallReturn answer = {};
404 SharedMemIPCClient ipc(ipc_memory);
405 ResultCode code =
406 CrossCall(ipc, IPC_GDI_GETOPMINFORMATION_TAG,
407 static_cast<void*>(protected_output), buffer.handle(), &answer);
408
409 if (code != SBOX_ALL_OK)
410 return STATUS_ACCESS_DENIED;
411
412 if (!answer.nt_status) {
413 memcpy(requested_information, buffer.memory(),
414 sizeof(*requested_information));
415 }
416
417 return answer.nt_status;
418 }
419
420 NTSTATUS WINAPI
421 TargetGetOPMRandomNumber(GetOPMRandomNumberFunction,
422 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
423 DXGKMDT_OPM_RANDOM_NUMBER* random_number) {
424 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
425 return STATUS_ACCESS_DENIED;
426 void* ipc_memory = GetGlobalIPCMemory();
427 if (ipc_memory == NULL)
428 return STATUS_ACCESS_DENIED;
429
430 CrossCallReturn answer = {};
431 SharedMemIPCClient ipc(ipc_memory);
432 InOutCountedBuffer buffer(random_number, sizeof(*random_number));
433 ResultCode code =
434 CrossCall(ipc, IPC_GDI_GETOPMRANDOMNUMBER_TAG,
435 static_cast<void*>(protected_output), buffer, &answer);
436
437 if (code != SBOX_ALL_OK)
438 return STATUS_ACCESS_DENIED;
439
440 return answer.nt_status;
441 }
442
443 NTSTATUS WINAPI TargetGetSuggestedOPMProtectedOutputArraySize(
444 GetSuggestedOPMProtectedOutputArraySizeFunction,
445 PUNICODE_STRING device_name,
446 DWORD* suggested_output_size) {
447 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
448 return STATUS_ACCESS_DENIED;
449 void* ipc_memory = GetGlobalIPCMemory();
450 if (ipc_memory == NULL)
451 return STATUS_ACCESS_DENIED;
452
453 CrossCallReturn answer = {};
454 SharedMemIPCClient ipc(ipc_memory);
455 base::string16 device_name_str;
456 UnicodeStringToString(device_name, &device_name_str);
457 ResultCode code =
458 CrossCall(ipc, IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG,
459 device_name_str.c_str(), &answer);
460
461 if (code != SBOX_ALL_OK)
462 return STATUS_ACCESS_DENIED;
463
464 if (!answer.nt_status)
465 *suggested_output_size = answer.extended[0].unsigned_int;
466
467 return answer.nt_status;
468 }
469
470 NTSTATUS WINAPI TargetSetOPMSigningKeyAndSequenceNumbers(
471 SetOPMSigningKeyAndSequenceNumbersFunction,
472 OPM_PROTECTED_OUTPUT_HANDLE protected_output,
473 const DXGKMDT_OPM_ENCRYPTED_PARAMETERS* parameters) {
474 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
475 return STATUS_ACCESS_DENIED;
476 void* ipc_memory = GetGlobalIPCMemory();
477 if (ipc_memory == NULL)
478 return STATUS_ACCESS_DENIED;
479
480 DXGKMDT_OPM_ENCRYPTED_PARAMETERS temp_parameters = *parameters;
481
482 CrossCallReturn answer = {};
483 SharedMemIPCClient ipc(ipc_memory);
484 InOutCountedBuffer buffer(&temp_parameters, sizeof(temp_parameters));
485 ResultCode code =
486 CrossCall(ipc, IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG,
487 static_cast<void*>(protected_output), buffer, &answer);
488
489 if (code != SBOX_ALL_OK)
490 return STATUS_ACCESS_DENIED;
491
492 return answer.nt_status;
493 }
494
495 NTSTATUS WINAPI
496 TargetCreateOPMProtectedOutputs(CreateOPMProtectedOutputsFunction,
497 PUNICODE_STRING device_name,
498 DXGKMDT_OPM_VIDEO_OUTPUT_SEMANTICS vos,
499 DWORD outputs_array_size,
500 DWORD* output_size,
501 OPM_PROTECTED_OUTPUT_HANDLE* outputs_array) {
502 if (vos != DXGKMDT_OPM_VOS_OPM_SEMANTICS)
503 return STATUS_INVALID_PARAMETER;
504
505 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
506 return STATUS_ACCESS_DENIED;
507 void* ipc_memory = GetGlobalIPCMemory();
508 if (ipc_memory == NULL)
509 return STATUS_ACCESS_DENIED;
510
511 CrossCallReturn answer = {};
512 SharedMemIPCClient ipc(ipc_memory);
513 base::CheckedNumeric<uint32_t> array_size = outputs_array_size;
514 array_size *= sizeof(HANDLE);
515 if (!array_size.IsValid())
516 return STATUS_INVALID_PARAMETER;
517
518 InOutCountedBuffer buffer(outputs_array, array_size.ValueOrDie());
519 base::string16 device_name_str;
520 UnicodeStringToString(device_name, &device_name_str);
521 ResultCode code = CrossCall(ipc, IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG,
522 device_name_str.c_str(), buffer, &answer);
523
524 if (code != SBOX_ALL_OK)
525 return STATUS_ACCESS_DENIED;
526
527 if (!answer.nt_status)
528 *output_size = answer.extended[0].unsigned_int;
529
530 return answer.nt_status;
531 }
532
28 } // namespace sandbox 533 } // namespace sandbox
29 534
OLDNEW
« no previous file with comments | « sandbox/win/src/process_mitigations_win32k_interception.h ('k') | sandbox/win/src/process_mitigations_win32k_policy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698