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 <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 DCHECK(!!RtlInitUnicodeString); | |
49 } | |
50 RtlInitUnicodeString(unicode_string, device_name.c_str()); | |
51 } | |
52 | |
53 struct MonitorListState { | |
54 HMONITOR* monitor_list; | |
55 uint32_t monitor_list_size; | |
56 uint32_t monitor_list_pos; | |
57 }; | |
58 | |
59 BOOL CALLBACK DisplayMonitorEnumProc(HMONITOR monitor, | |
60 HDC hdc_monitor, | |
61 LPRECT rect_monitor, | |
62 LPARAM data) { | |
63 MonitorListState* state = reinterpret_cast<MonitorListState*>(data); | |
64 if (state->monitor_list_pos >= state->monitor_list_size) | |
65 return FALSE; | |
66 state->monitor_list[state->monitor_list_pos++] = monitor; | |
67 return TRUE; | |
68 } | |
69 | |
70 template <typename T> | |
71 T GetGdi32Func(const char* name) { | |
72 static T func = nullptr; | |
73 if (!func) { | |
74 func = reinterpret_cast<T>( | |
75 ::GetProcAddress(::GetModuleHandle(L"gdi32.dll"), name)); | |
76 DCHECK(!!func); | |
77 } | |
78 return func; | |
79 } | |
80 | |
81 #define GDIFUNC(name) GetGdi32Func<name##Function>(#name) | |
82 | |
83 } // namespace | |
84 | |
9 bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( | 85 bool ProcessMitigationsWin32KLockdownPolicy::GenerateRules( |
10 const wchar_t* name, | 86 const wchar_t* name, |
11 TargetPolicy::Semantics semantics, | 87 TargetPolicy::Semantics semantics, |
12 LowLevelPolicy* policy) { | 88 LowLevelPolicy* policy) { |
13 PolicyRule rule(FAKE_SUCCESS); | 89 PolicyRule rule(FAKE_SUCCESS); |
14 if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule)) | 90 if (!policy->AddRule(IPC_GDI_GDIDLLINITIALIZE_TAG, &rule)) |
15 return false; | 91 return false; |
16 if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule)) | 92 if (!policy->AddRule(IPC_GDI_GETSTOCKOBJECT_TAG, &rule)) |
17 return false; | 93 return false; |
18 if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule)) | 94 if (!policy->AddRule(IPC_USER_REGISTERCLASSW_TAG, &rule)) |
19 return false; | 95 return false; |
96 if (semantics != TargetPolicy::IMPLEMENT_OPM_APIS) | |
97 return true; | |
98 if (!policy->AddRule(IPC_USER_ENUMDISPLAYMONITORS_TAG, &rule)) | |
99 return false; | |
100 if (!policy->AddRule(IPC_USER_ENUMDISPLAYDEVICES_TAG, &rule)) | |
101 return false; | |
102 if (!policy->AddRule(IPC_USER_GETMONITORINFO_TAG, &rule)) | |
103 return false; | |
104 if (!policy->AddRule(IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG, &rule)) | |
105 return false; | |
106 if (!policy->AddRule(IPC_GDI_GETCERTIFICATE_TAG, &rule)) | |
107 return false; | |
108 if (!policy->AddRule(IPC_GDI_GETCERTIFICATESIZE_TAG, &rule)) | |
109 return false; | |
110 if (!policy->AddRule(IPC_GDI_DESTROYOPMPROTECTEDOUTPUT_TAG, &rule)) | |
111 return false; | |
112 if (!policy->AddRule(IPC_GDI_CONFIGUREOPMPROTECTEDOUTPUT_TAG, &rule)) | |
113 return false; | |
114 if (!policy->AddRule(IPC_GDI_GETOPMINFORMATION_TAG, &rule)) | |
115 return false; | |
116 if (!policy->AddRule(IPC_GDI_GETOPMRANDOMNUMBER_TAG, &rule)) | |
117 return false; | |
118 if (!policy->AddRule(IPC_GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE_TAG, | |
119 &rule)) | |
120 return false; | |
121 if (!policy->AddRule(IPC_GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS_TAG, &rule)) | |
122 return false; | |
20 return true; | 123 return true; |
21 } | 124 } |
22 | 125 |
126 uint32_t ProcessMitigationsWin32KLockdownPolicy::EnumDisplayMonitorsAction( | |
127 const ClientInfo& client_info, | |
128 HMONITOR* monitor_list, | |
129 uint32_t monitor_list_size) { | |
130 MonitorListState state = {monitor_list, monitor_list_size, 0}; | |
131 EnumDisplayMonitors(nullptr, nullptr, DisplayMonitorEnumProc, | |
132 reinterpret_cast<LPARAM>(&state)); | |
133 return state.monitor_list_pos; | |
134 } | |
135 | |
136 NTSTATUS ProcessMitigationsWin32KLockdownPolicy:: | |
137 GetSuggestedOPMProtectedOutputArraySizeAction( | |
138 const ClientInfo& client_info, | |
139 const base::string16& device_name, | |
140 uint32_t* suggested_array_size) { | |
141 UNICODE_STRING unicode_device_name; | |
142 StringToUnicodeString(&unicode_device_name, device_name); | |
143 return GDIFUNC(GetSuggestedOPMProtectedOutputArraySize)( | |
144 &unicode_device_name, reinterpret_cast<DWORD*>(suggested_array_size)); | |
145 } | |
146 | |
147 NTSTATUS | |
148 ProcessMitigationsWin32KLockdownPolicy::CreateOPMProtectedOutputsAction( | |
149 const ClientInfo& client_info, | |
150 const base::string16& device_name, | |
151 HANDLE* protected_outputs, | |
152 uint32_t array_input_size, | |
153 uint32_t* array_output_size) { | |
154 UNICODE_STRING unicode_device_name; | |
155 StringToUnicodeString(&unicode_device_name, device_name); | |
156 DWORD output_size = 0; | |
157 | |
158 NTSTATUS status = GDIFUNC(CreateOPMProtectedOutputs)( | |
159 &unicode_device_name, DXGKMDT_OPM_VOS_OPM_SEMANTICS, array_input_size, | |
160 &output_size, | |
161 reinterpret_cast<OPM_PROTECTED_OUTPUT_HANDLE*>(protected_outputs)); | |
162 if (!status) | |
163 *array_output_size = output_size; | |
164 return status; | |
165 } | |
166 | |
167 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateSizeAction( | |
168 const ClientInfo& client_info, | |
169 const base::string16& device_name, | |
170 uint32_t* cert_size) { | |
171 UNICODE_STRING unicode_device_name; | |
172 StringToUnicodeString(&unicode_device_name, device_name); | |
173 | |
174 return GDIFUNC(GetCertificateSize)(&unicode_device_name, | |
175 DXGKMDT_OPM_CERTIFICATE, | |
176 reinterpret_cast<DWORD*>(cert_size)); | |
177 } | |
178 | |
179 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetCertificateAction( | |
180 const ClientInfo& client_info, | |
181 const base::string16& device_name, | |
182 BYTE* cert_data, | |
183 uint32_t cert_size) { | |
184 UNICODE_STRING unicode_device_name; | |
185 StringToUnicodeString(&unicode_device_name, device_name); | |
186 | |
187 return GDIFUNC(GetCertificate)(&unicode_device_name, DXGKMDT_OPM_CERTIFICATE, | |
188 cert_data, cert_size); | |
189 } | |
190 | |
191 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMRandomNumberAction( | |
192 const ClientInfo& client_info, | |
193 HANDLE protected_output, | |
194 void* random_number) { | |
195 return GDIFUNC(GetOPMRandomNumber)( | |
196 protected_output, static_cast<DXGKMDT_OPM_RANDOM_NUMBER*>(random_number)); | |
Will Harris
2016/04/05 03:49:02
reinterpret_cast
Will Harris
2016/04/11 21:23:02
actually static_cast here is fine.
| |
197 } | |
198 | |
199 NTSTATUS ProcessMitigationsWin32KLockdownPolicy:: | |
200 SetOPMSigningKeyAndSequenceNumbersAction(const ClientInfo& client_info, | |
201 HANDLE protected_output, | |
202 void* parameters) { | |
203 return GDIFUNC(SetOPMSigningKeyAndSequenceNumbers)( | |
204 protected_output, | |
205 static_cast<DXGKMDT_OPM_ENCRYPTED_PARAMETERS*>(parameters)); | |
206 } | |
207 | |
208 NTSTATUS | |
209 ProcessMitigationsWin32KLockdownPolicy::ConfigureOPMProtectedOutputAction( | |
210 const ClientInfo& client_info, | |
211 HANDLE protected_output, | |
212 void* parameters) { | |
213 DXGKMDT_OPM_CONFIGURE_PARAMETERS config; | |
214 memcpy(&config, parameters, sizeof(DXGKMDT_OPM_CONFIGURE_PARAMETERS)); | |
215 if (config.guidSetting != DXGKMDT_OPM_SET_PROTECTION_LEVEL || | |
216 config.cbParametersSize != | |
217 sizeof(DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS)) { | |
218 return STATUS_INVALID_PARAMETER; | |
219 } | |
220 | |
221 DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS params; | |
222 memcpy(¶ms, config.abParameters, | |
223 sizeof(DXGKMDT_OPM_SET_PROTECTION_LEVEL_PARAMETERS)); | |
224 if (params.Reserved || params.Reserved2) | |
225 return STATUS_INVALID_PARAMETER; | |
226 | |
227 if (params.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_HDCP && | |
228 params.ulProtectionType != DXGKMDT_OPM_PROTECTION_TYPE_DPCP) { | |
229 return STATUS_INVALID_PARAMETER; | |
230 } | |
231 | |
232 // Protection levels are same for HDCP and DPCP. | |
233 if (params.ulProtectionLevel != DXGKMDT_OPM_HDCP_OFF && | |
234 params.ulProtectionLevel != DXGKMDT_OPM_HDCP_ON) { | |
235 return STATUS_INVALID_PARAMETER; | |
236 } | |
237 | |
238 return GDIFUNC(ConfigureOPMProtectedOutput)(protected_output, &config, 0, | |
239 nullptr); | |
240 } | |
241 | |
242 NTSTATUS ProcessMitigationsWin32KLockdownPolicy::GetOPMInformationAction( | |
243 const ClientInfo& client_info, | |
244 HANDLE protected_output, | |
245 void* parameters, | |
246 void* requested_information) { | |
247 DXGKMDT_OPM_GET_INFO_PARAMETERS params; | |
248 memcpy(¶ms, parameters, sizeof(DXGKMDT_OPM_GET_INFO_PARAMETERS)); | |
249 | |
250 bool valid_parameters = false; | |
251 // Validate sizes based on the type being requested. | |
252 if ((params.guidInformation == DXGKMDT_OPM_GET_CONNECTOR_TYPE || | |
253 params.guidInformation == DXGKMDT_OPM_GET_SUPPORTED_PROTECTION_TYPES) && | |
254 params.cbParametersSize == 0) { | |
255 valid_parameters = true; | |
256 } else if ((params.guidInformation == | |
257 DXGKMDT_OPM_GET_VIRTUAL_PROTECTION_LEVEL || | |
258 params.guidInformation == | |
259 DXGKMDT_OPM_GET_ACTUAL_PROTECTION_LEVEL) && | |
260 params.cbParametersSize == sizeof(uint32_t)) { | |
261 uint32_t param_value; | |
262 memcpy(¶m_value, params.abParameters, sizeof(uint32_t)); | |
263 if (param_value == DXGKMDT_OPM_PROTECTION_TYPE_HDCP || | |
264 param_value == DXGKMDT_OPM_PROTECTION_TYPE_DPCP) { | |
265 valid_parameters = true; | |
266 } | |
267 } | |
268 if (!valid_parameters) | |
269 return STATUS_INVALID_PARAMETER; | |
270 | |
271 return GDIFUNC(GetOPMInformation)( | |
272 protected_output, ¶ms, | |
273 static_cast<DXGKMDT_OPM_REQUESTED_INFORMATION*>(requested_information)); | |
274 } | |
275 | |
276 NTSTATUS | |
277 ProcessMitigationsWin32KLockdownPolicy::DestroyOPMProtectedOutputAction( | |
278 HANDLE protected_output) { | |
279 return GDIFUNC(DestroyOPMProtectedOutput)(protected_output); | |
280 } | |
281 | |
23 } // namespace sandbox | 282 } // namespace sandbox |
24 | 283 |
OLD | NEW |