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

Side by Side Diff: sandbox/win/src/process_mitigations_win32k_policy.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
« no previous file with comments | « sandbox/win/src/process_mitigations_win32k_policy.h ('k') | sandbox/win/src/sandbox_policy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stddef.h>
6
7 #include "sandbox/win/src/process_mitigations_win32k_interception.h"
5 #include "sandbox/win/src/process_mitigations_win32k_policy.h" 8 #include "sandbox/win/src/process_mitigations_win32k_policy.h"
6 9
7 namespace sandbox { 10 namespace sandbox {
8 11
12 namespace {
13
14 // Define GUIDs for OPM APIs
15 const GUID DXGKMDT_OPM_GET_CONNECTOR_TYPE = {
16 0x81d0bfd5,
17 0x6afe,
18 0x48c2,
19 {0x99, 0xc0, 0x95, 0xa0, 0x8f, 0x97, 0xc5, 0xda}};
20 const GUID DXGKMDT_OPM_GET_SUPPORTED_PROTECTION_TYPES = {
21 0x38f2a801,
22 0x9a6c,
23 0x48bb,
24 {0x91, 0x07, 0xb6, 0x69, 0x6e, 0x6f, 0x17, 0x97}};
25 const GUID DXGKMDT_OPM_GET_VIRTUAL_PROTECTION_LEVEL = {
26 0xb2075857,
27 0x3eda,
28 0x4d5d,
29 {0x88, 0xdb, 0x74, 0x8f, 0x8c, 0x1a, 0x05, 0x49}};
30 const GUID DXGKMDT_OPM_GET_ACTUAL_PROTECTION_LEVEL = {
31 0x1957210a,
32 0x7766,
33 0x452a,
34 {0xb9, 0x9a, 0xd2, 0x7a, 0xed, 0x54, 0xf0, 0x3a}};
35 const GUID DXGKMDT_OPM_SET_PROTECTION_LEVEL = {
36 0x9bb9327c,
37 0x4eb5,
38 0x4727,
39 {0x9f, 0x00, 0xb4, 0x2b, 0x09, 0x19, 0xc0, 0xda}};
40
41 void StringToUnicodeString(PUNICODE_STRING unicode_string,
42 const base::string16& device_name) {
43 static RtlInitUnicodeStringFunction RtlInitUnicodeString;
44 if (!RtlInitUnicodeString) {
45 HMODULE ntdll = ::GetModuleHandle(kNtdllName);
46 RtlInitUnicodeString = reinterpret_cast<RtlInitUnicodeStringFunction>(
47 GetProcAddress(ntdll, "RtlInitUnicodeString"));
48 }
49 RtlInitUnicodeString(unicode_string, device_name.c_str());
50 }
51
52 struct MonitorListState {
53 HMONITOR* monitor_list;
54 uint32_t monitor_list_size;
55 uint32_t monitor_list_pos;
56 };
57
58 BOOL CALLBACK DisplayMonitorEnumProc(HMONITOR monitor,
59 HDC hdc_monitor,
60 LPRECT rect_monitor,
61 LPARAM data) {
62 MonitorListState* state = reinterpret_cast<MonitorListState*>(data);
63 if (state->monitor_list_pos >= state->monitor_list_size)
64 return FALSE;
65 state->monitor_list[state->monitor_list_pos++] = monitor;
66 return TRUE;
67 }
68
69 template <typename T>
70 T GetExportedFunc(const wchar_t* libname, const char* name) {
71 OverrideForTestFunction test_override =
72 ProcessMitigationsWin32KLockdownPolicy::GetOverrideForTestCallback();
73 if (test_override)
74 return reinterpret_cast<T>(test_override(name));
75
76 static T func = nullptr;
77 if (!func) {
78 func =
79 reinterpret_cast<T>(::GetProcAddress(::GetModuleHandle(libname), name));
80 DCHECK(!!func);
81 }
82 return func;
83 }
84
85 #define GDIFUNC(name) GetExportedFunc<name##Function>(L"gdi32.dll", #name)
86 #define USERFUNC(name) GetExportedFunc<name##Function>(L"user32.dll", #name)
87
88 struct ValidateMonitorParams {
89 HMONITOR monitor;
90 base::string16 device_name;
91 bool result;
92 };
93
94 bool GetMonitorDeviceName(HMONITOR monitor, base::string16* device_name) {
95 MONITORINFOEXW monitor_info = {};
96 monitor_info.cbSize = sizeof(monitor_info);
97 if (!USERFUNC(GetMonitorInfoW)(monitor, &monitor_info))
98 return false;
99 if (monitor_info.szDevice[CCHDEVICENAME - 1] != 0)
100 return false;
101 *device_name = monitor_info.szDevice;
102 return true;
103 }
104
105 BOOL CALLBACK ValidateMonitorEnumProc(HMONITOR monitor,
106 HDC,
107 LPRECT,
108 LPARAM data) {
109 ValidateMonitorParams* valid_params =
110 reinterpret_cast<ValidateMonitorParams*>(data);
111 base::string16 device_name;
112 bool result = false;
113 if (valid_params->device_name.empty()) {
114 result = monitor == valid_params->monitor;
115 } else if (GetMonitorDeviceName(monitor, &device_name)) {
116 result = device_name == valid_params->device_name;
117 }
118 valid_params->result = result;
119 if (!result)
120 return TRUE;
121 return FALSE;
122 }
123
124 bool IsValidMonitorOrDeviceName(HMONITOR monitor, const wchar_t* device_name) {
125 ValidateMonitorParams params = {};
126 params.monitor = monitor;
127 if (device_name)
128 params.device_name = device_name;
129 USERFUNC(EnumDisplayMonitors)
130 (nullptr, nullptr, ValidateMonitorEnumProc,
131 reinterpret_cast<LPARAM>(&params));
132 return params.result;
133 }
134
135 } // namespace
136
137 OverrideForTestFunction
138 ProcessMitigationsWin32KLockdownPolicy::override_callback_;
139
9 bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( 140 bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
10 const wchar_t* name, 141 const wchar_t* name,
11 TargetPolicy::Semantics semantics, 142 TargetPolicy::Semantics semantics,
12 LowLevelPolicy* policy) { 143 LowLevelPolicy* policy) {
13 PolicyRule rule(FAKE_SUCCESS); 144 PolicyRule rule(FAKE_SUCCESS);
14 if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule)) 145 if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule))
15 return false; 146 return false;
16 if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule)) 147 if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule))
17 return false; 148 return false;
18 if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule)) 149 if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule))
19 return false; 150 return false;
151 if (semantics != TargetPolicy::IMPLEMENT_OPM_APIS)
152 return true;
153 if (!policy->AddRule(IPC_USER_ENUMDISPLAYMONITORS_TAG, &rule))
154 return false;
155 if (!policy->AddRule(IPC_USER_ENUMDISPLAYDEVICES_TAG, &rule))
156 return false;
157 if (!policy->AddRule(IPC_USER_GETMONITORINFO_TAG, &rule))
158 return false;
159 if (!policy->AddRule(IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG, &rule))
160 return false;
161 if (!policy->AddRule(IPC_GDI_GETCERTIFICATE_TAG, &rule))
162 return false;
163 if (!policy->AddRule(IPC_GDI_GETCERTIFICATESIZE_TAG, &rule))
164 return false;
165 if (!policy->AddRule(IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG, &rule))
166 return false;
167 if (!policy->AddRule(IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG, &rule))
168 return false;
169 if (!policy->AddRule(IPC_GDI_GETOPMINFORMATION_TAG, &rule))
170 return false;
171 if (!policy->AddRule(IPC_GDI_GETOPMRANDOMNUMBER_TAG, &rule))
172 return false;
173 if (!policy->AddRule(IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG,
174 &rule))
175 return false;
176 if (!policy->AddRule(IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG, &rule))
177 return false;
20 return true; 178 return true;
21 } 179 }
22 180
181 uint32_t ProcessMitigationsWin32KLockdownPolicy::EnumDisplayMonitorsAction(
182 const ClientInfo& client_info,
183 HMONITOR* monitor_list,
184 uint32_t monitor_list_size) {
185 MonitorListState state = {monitor_list, monitor_list_size, 0};
186 USERFUNC(EnumDisplayMonitors)
187 (nullptr, nullptr, DisplayMonitorEnumProc, reinterpret_cast<LPARAM>(&state));
188 return state.monitor_list_pos;
189 }
190
191 BOOL ProcessMitigationsWin32KLockdownPolicy::GetMonitorInfoAction(
192 const ClientInfo& client_info,
193 HMONITOR monitor,
194 MONITORINFO* monitor_info_ptr) {
195 if (!IsValidMonitorOrDeviceName(monitor, nullptr))
196 return FALSE;
197 MONITORINFOEXW monitor_info = {};
198 monitor_info.cbSize = sizeof(MONITORINFOEXW);
199
200 BOOL success = USERFUNC(GetMonitorInfoW)(
201 monitor, reinterpret_cast<MONITORINFO*>(&monitor_info));
202 if (success)
203 memcpy(monitor_info_ptr, &monitor_info, sizeof(monitor_info));
204 return success;
205 }
206
207 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::
208 GetSuggestedOPMProtectedOutputArraySizeAction(
209 const ClientInfo& client_info,
210 const base::string16& device_name,
211 uint32_t* suggested_array_size) {
212 if (!IsValidMonitorOrDeviceName(nullptr, device_name.c_str())) {
213 return STATUS_ACCESS_DENIED;
214 }
215 UNICODE_STRING unicode_device_name;
216 StringToUnicodeString(&unicode_device_name, device_name);
217 DWORD suggested_array_size_dword = 0;
218 NTSTATUS status = GDIFUNC(GetSuggestedOPMProtectedOutputArraySize)(
219 &unicode_device_name, &suggested_array_size_dword);
220 if (!status)
221 *suggested_array_size = suggested_array_size_dword;
222 return status;
223 }
224
225 NTSTATUS
226 ProcessMitigationsWin32KLockdownPolicy::CreateOPMProtectedOutputsAction(
227 const ClientInfo& client_info,
228 const base::string16& device_name,
229 HANDLE* protected_outputs,
230 uint32_t array_input_size,
231 uint32_t* array_output_size) {
232 if (!IsValidMonitorOrDeviceName(nullptr, device_name.c_str())) {
233 return STATUS_ACCESS_DENIED;
234 }
235
236 UNICODE_STRING unicode_device_name;
237 StringToUnicodeString(&unicode_device_name, device_name);
238 DWORD output_size = 0;
239
240 NTSTATUS status = GDIFUNC(CreateOPMProtectedOutputs)(
241 &unicode_device_name, DXGKMDT_OPM_VOS_OPM_SEMANTICS, array_input_size,
242 &output_size,
243 reinterpret_cast<OPM_PROTECTED_OUTPUT_HANDLE*>(protected_outputs));
244 if (!status)
245 *array_output_size = output_size;
246 return status;
247 }
248
249 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateSizeAction(
250 const ClientInfo& client_info,
251 const base::string16& device_name,
252 uint32_t* cert_size) {
253 if (!IsValidMonitorOrDeviceName(nullptr, device_name.c_str())) {
254 return STATUS_ACCESS_DENIED;
255 }
256 UNICODE_STRING unicode_device_name;
257 StringToUnicodeString(&unicode_device_name, device_name);
258
259 return GDIFUNC(GetCertificateSize)(&unicode_device_name,
260 DXGKMDT_OPM_CERTIFICATE,
261 reinterpret_cast<DWORD*>(cert_size));
262 }
263
264 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateAction(
265 const ClientInfo& client_info,
266 const base::string16& device_name,
267 BYTE* cert_data,
268 uint32_t cert_size) {
269 if (!IsValidMonitorOrDeviceName(nullptr, device_name.c_str())) {
270 return STATUS_ACCESS_DENIED;
271 }
272 UNICODE_STRING unicode_device_name;
273 StringToUnicodeString(&unicode_device_name, device_name);
274
275 return GDIFUNC(GetCertificate)(&unicode_device_name, DXGKMDT_OPM_CERTIFICATE,
276 cert_data, cert_size);
277 }
278
279 NTSTATUS
280 ProcessMitigationsWin32KLockdownPolicy::GetCertificateSizeByHandleAction(
281 const ClientInfo& client_info,
282 HANDLE protected_output,
283 uint32_t* cert_size) {
284 auto get_certificate_size_func = GDIFUNC(GetCertificateSizeByHandle);
285 if (get_certificate_size_func) {
286 return get_certificate_size_func(protected_output, DXGKMDT_OPM_CERTIFICATE,
287 reinterpret_cast<DWORD*>(cert_size));
288 }
289 return STATUS_NOT_IMPLEMENTED;
290 }
291
292 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateByHandleAction(
293 const ClientInfo& client_info,
294 HANDLE protected_output,
295 BYTE* cert_data,
296 uint32_t cert_size) {
297 auto get_certificate_func = GDIFUNC(GetCertificateByHandle);
298 if (get_certificate_func) {
299 return get_certificate_func(protected_output, DXGKMDT_OPM_CERTIFICATE,
300 cert_data, cert_size);
301 }
302 return STATUS_NOT_IMPLEMENTED;
303 }
304
305 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMRandomNumberAction(
306 const ClientInfo& client_info,
307 HANDLE protected_output,
308 void* random_number) {
309 return GDIFUNC(GetOPMRandomNumber)(
310 protected_output, static_cast<DXGKMDT_OPM_RANDOM_NUMBER*>(random_number));
311 }
312
313 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::
314 SetOPMSigningKeyAndSequenceNumbersAction(const ClientInfo& client_info,
315 HANDLE protected_output,
316 void* parameters) {
317 return GDIFUNC(SetOPMSigningKeyAndSequenceNumbers)(
318 protected_output,
319 static_cast<DXGKMDT_OPM_ENCRYPTED_PARAMETERS*>(parameters));
320 }
321
322 NTSTATUS
323 ProcessMitigationsWin32KLockdownPolicy::ConfigureOPMProtectedOutputAction(
324 const ClientInfo& client_info,
325 HANDLE protected_output,
326 void* parameters_ptr) {
327 DXGKMDT_OPM_CONFIGURE_PARAMETERS parameters;
328 memcpy(&parameters, parameters_ptr, sizeof(parameters));
329 if (parameters.guidSetting != DXGKMDT_OPM_SET_PROTECTION_LEVEL ||
330 parameters.cbParametersSize !=
331 sizeof(DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS)) {
332 return STATUS_INVALID_PARAMETER;
333 }
334
335 DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS prot_level;
336 memcpy(&prot_level, parameters.abParameters, sizeof(prot_level));
337 if (prot_level.Reserved || prot_level.Reserved2)
338 return STATUS_INVALID_PARAMETER;
339
340 if (prot_level.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_HDCP &&
341 prot_level.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_DPCP) {
342 return STATUS_INVALID_PARAMETER;
343 }
344
345 // Protection levels are same for HDCP and DPCP.
346 if (prot_level.ulProtectionLevel != DXGKMDT_OPM_HDCP_OFF &&
347 prot_level.ulProtectionLevel != DXGKMDT_OPM_HDCP_ON) {
348 return STATUS_INVALID_PARAMETER;
349 }
350
351 return GDIFUNC(ConfigureOPMProtectedOutput)(protected_output, &parameters, 0,
352 nullptr);
353 }
354
355 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMInformationAction(
356 const ClientInfo& client_info,
357 HANDLE protected_output,
358 void* parameters_ptr,
359 void* requested_info_ptr) {
360 DXGKMDT_OPM_GET_INFO_PARAMETERS parameters;
361 memcpy(&parameters, parameters_ptr, sizeof(parameters));
362
363 bool valid_parameters = false;
364 // Validate sizes based on the type being requested.
365 if ((parameters.guidInformation == DXGKMDT_OPM_GET_CONNECTOR_TYPE ||
366 parameters.guidInformation ==
367 DXGKMDT_OPM_GET_SUPPORTED_PROTECTION_TYPES) &&
368 parameters.cbParametersSize == 0) {
369 valid_parameters = true;
370 } else if ((parameters.guidInformation ==
371 DXGKMDT_OPM_GET_VIRTUAL_PROTECTION_LEVEL ||
372 parameters.guidInformation ==
373 DXGKMDT_OPM_GET_ACTUAL_PROTECTION_LEVEL) &&
374 parameters.cbParametersSize == sizeof(uint32_t)) {
375 uint32_t param_value;
376 memcpy(&param_value, parameters.abParameters, sizeof(param_value));
377 if (param_value == DXGKMDT_OPM_PROTECTION_TYPE_HDCP ||
378 param_value == DXGKMDT_OPM_PROTECTION_TYPE_DPCP) {
379 valid_parameters = true;
380 }
381 }
382 if (!valid_parameters)
383 return STATUS_INVALID_PARAMETER;
384 DXGKMDT_OPM_REQUESTED_INFORMATION requested_info = {};
385 NTSTATUS status = GDIFUNC(GetOPMInformation)(protected_output, &parameters,
386 &requested_info);
387 if (!status)
388 memcpy(requested_info_ptr, &requested_info, sizeof(requested_info));
389
390 return status;
391 }
392
393 NTSTATUS
394 ProcessMitigationsWin32KLockdownPolicy::DestroyOPMProtectedOutputAction(
395 HANDLE protected_output) {
396 return GDIFUNC(DestroyOPMProtectedOutput)(protected_output);
397 }
398
399 void ProcessMitigationsWin32KLockdownPolicy::SetOverrideForTestCallback(
400 OverrideForTestFunction callback) {
401 override_callback_ = callback;
402 }
403
404 OverrideForTestFunction
405 ProcessMitigationsWin32KLockdownPolicy::GetOverrideForTestCallback() {
406 return override_callback_;
407 }
408
23 } // namespace sandbox 409 } // namespace sandbox
24 410
OLDNEW
« no previous file with comments | « sandbox/win/src/process_mitigations_win32k_policy.h ('k') | sandbox/win/src/sandbox_policy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698