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

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

Powered by Google App Engine
This is Rietveld 408576698