OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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.h" | 5 #include "sandbox/win/src/process_mitigations.h" |
6 | 6 |
7 #include "base/win/windows_version.h" | 7 #include "base/win/windows_version.h" |
8 #include "sandbox/win/src/nt_internals.h" | 8 #include "sandbox/win/src/nt_internals.h" |
9 #include "sandbox/win/src/sandbox_types.h" | |
10 #include "sandbox/win/src/sandbox_utils.h" | 9 #include "sandbox/win/src/sandbox_utils.h" |
11 #include "sandbox/win/src/target_process.h" | |
12 #include "sandbox/win/src/win_utils.h" | 10 #include "sandbox/win/src/win_utils.h" |
13 | 11 |
14 namespace { | 12 namespace { |
15 | 13 |
16 // Functions for enabling policies. | 14 // Functions for enabling policies. |
17 typedef BOOL (WINAPI *SetProcessDEPPolicyFunction)(DWORD dwFlags); | 15 typedef BOOL (WINAPI *SetProcessDEPPolicyFunction)(DWORD dwFlags); |
18 | 16 |
19 typedef BOOL (WINAPI *SetProcessMitigationPolicyFunction)( | 17 typedef BOOL (WINAPI *SetProcessMitigationPolicyFunction)( |
20 PROCESS_MITIGATION_POLICY mitigation_policy, | 18 PROCESS_MITIGATION_POLICY mitigation_policy, |
21 PVOID buffer, | 19 PVOID buffer, |
22 SIZE_T length); | 20 SIZE_T length); |
23 | 21 |
24 typedef BOOL (WINAPI *SetDefaultDllDirectoriesFunction)( | 22 typedef BOOL (WINAPI *SetDefaultDllDirectoriesFunction)( |
25 DWORD DirectoryFlags); | 23 DWORD DirectoryFlags); |
26 | 24 |
27 void CALLBACK ApplyMitigationsCallback(ULONG_PTR flags) { | |
28 if (!sandbox::ApplyProcessMitigationsToCurrentProcess(flags)) | |
29 ::TerminateProcess(::GetCurrentProcess(), sandbox::SBOX_FATAL_MITIGATION); | |
30 } | |
31 | |
32 } // namespace | 25 } // namespace |
33 | 26 |
34 namespace sandbox { | 27 namespace sandbox { |
35 | 28 |
36 bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags) { | 29 bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags) { |
37 if (!CanSetProcessMitigationsPostStartup(flags)) | 30 if (!CanSetProcessMitigationsPostStartup(flags)) |
38 return false; | 31 return false; |
39 | 32 |
40 // We can't apply anything before Win XP, so just return cleanly. | 33 // We can't apply anything before Win XP, so just return cleanly. |
41 if (!IsXPSP2OrLater()) | 34 if (!IsXPSP2OrLater()) |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON; | 238 PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON; |
246 } | 239 } |
247 | 240 |
248 if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { | 241 if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { |
249 *policy_flags |= | 242 *policy_flags |= |
250 PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; | 243 PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; |
251 } | 244 } |
252 } | 245 } |
253 | 246 |
254 MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags) { | 247 MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags) { |
| 248 // Anything prior to XP SP2. |
| 249 if (!IsXPSP2OrLater()) |
| 250 return 0; |
| 251 |
255 base::win::Version version = base::win::GetVersion(); | 252 base::win::Version version = base::win::GetVersion(); |
256 | 253 |
| 254 // Windows XP SP2+. |
257 if (version < base::win::VERSION_VISTA) { | 255 if (version < base::win::VERSION_VISTA) { |
258 return 0; | 256 return flags & (MITIGATION_DEP | |
| 257 MITIGATION_DEP_NO_ATL_THUNK); |
259 | 258 |
| 259 // Windows Vista |
| 260 if (version < base::win::VERSION_WIN7) { |
| 261 return flags & (MITIGATION_DEP | |
| 262 MITIGATION_DEP_NO_ATL_THUNK | |
| 263 MITIGATION_BOTTOM_UP_ASLR | |
| 264 MITIGATION_DLL_SEARCH_ORDER | |
| 265 MITIGATION_HEAP_TERMINATE); |
| 266 } |
| 267 |
| 268 // Windows 7 and Vista. |
260 } else if (version < base::win::VERSION_WIN8) { | 269 } else if (version < base::win::VERSION_WIN8) { |
261 return flags & (MITIGATION_DLL_SEARCH_ORDER | | 270 return flags & (MITIGATION_BOTTOM_UP_ASLR | |
| 271 MITIGATION_DLL_SEARCH_ORDER | |
262 MITIGATION_HEAP_TERMINATE); | 272 MITIGATION_HEAP_TERMINATE); |
263 } | 273 } |
264 | 274 |
265 // Windows 8 and above. | 275 // Windows 8 and above. |
266 return flags & (MITIGATION_DLL_SEARCH_ORDER); | 276 return flags & (MITIGATION_BOTTOM_UP_ASLR | |
| 277 MITIGATION_DLL_SEARCH_ORDER); |
267 } | 278 } |
268 | 279 |
269 bool ApplyProcessMitigationsToSuspendedTarget(TargetProcess* target, | 280 bool ApplyProcessMitigationsToSuspendedProcess(HANDLE process, |
270 MitigationFlags flags) { | 281 MitigationFlags flags) { |
| 282 // This is a hack to fake a weak bottom-up ASLR on 32-bit Windows. |
271 #if !defined(_WIN64) | 283 #if !defined(_WIN64) |
272 // This is a hack to fake a weak bottom-up ASLR on 32-bit Windows. | |
273 if (flags & MITIGATION_BOTTOM_UP_ASLR) { | 284 if (flags & MITIGATION_BOTTOM_UP_ASLR) { |
274 unsigned int limit; | 285 unsigned int limit; |
275 rand_s(&limit); | 286 rand_s(&limit); |
276 char* ptr = 0; | 287 char* ptr = 0; |
277 const size_t kMask64k = 0xFFFF; | 288 const size_t kMask64k = 0xFFFF; |
278 // Random range (512k-16.5mb) in 64k steps. | 289 // Random range (512k-16.5mb) in 64k steps. |
279 const char* end = ptr + ((((limit % 16384) + 512) * 1024) & ~kMask64k); | 290 const char* end = ptr + ((((limit % 16384) + 512) * 1024) & ~kMask64k); |
280 HANDLE process = target->Process(); | |
281 while (ptr < end) { | 291 while (ptr < end) { |
282 MEMORY_BASIC_INFORMATION memory_info; | 292 MEMORY_BASIC_INFORMATION memory_info; |
283 if (!::VirtualQueryEx(process, ptr, &memory_info, sizeof(memory_info))) | 293 if (!::VirtualQueryEx(process, ptr, &memory_info, sizeof(memory_info))) |
284 break; | 294 break; |
285 size_t size = std::min((memory_info.RegionSize + kMask64k) & ~kMask64k, | 295 size_t size = std::min((memory_info.RegionSize + kMask64k) & ~kMask64k, |
286 static_cast<SIZE_T>(end - ptr)); | 296 static_cast<SIZE_T>(end - ptr)); |
287 if (ptr && memory_info.State == MEM_FREE) | 297 if (ptr && memory_info.State == MEM_FREE) |
288 ::VirtualAllocEx(process, ptr, size, MEM_RESERVE, PAGE_NOACCESS); | 298 ::VirtualAllocEx(process, ptr, size, MEM_RESERVE, PAGE_NOACCESS); |
289 ptr += size; | 299 ptr += size; |
290 } | 300 } |
291 } | 301 } |
292 | |
293 // Since the process is suspended, we can schedule an APC to set the DEP | |
294 // policy immediately after then loader finishes. | |
295 ULONG_PTR dep_flags = flags & (MITIGATION_DEP | MITIGATION_DEP_NO_ATL_THUNK); | |
296 if (dep_flags && base::win::GetVersion() < base::win::VERSION_WIN7) { | |
297 if (!::QueueUserAPC(ApplyMitigationsCallback, target->MainThread(), | |
298 static_cast<ULONG_PTR>(dep_flags))) { | |
299 return false; | |
300 } | |
301 } | |
302 #endif | 302 #endif |
303 | 303 |
304 return true; | 304 return true; |
305 } | 305 } |
306 | 306 |
307 bool CanSetProcessMitigationsPostStartup(MitigationFlags flags) { | 307 bool CanSetProcessMitigationsPostStartup(MitigationFlags flags) { |
308 // All of these mitigations can be enabled after startup. | 308 // All of these mitigations can be enabled after startup. |
309 return !(flags & ~(MITIGATION_HEAP_TERMINATE | | 309 return !(flags & ~(MITIGATION_HEAP_TERMINATE | |
310 MITIGATION_DEP | | 310 MITIGATION_DEP | |
311 MITIGATION_DEP_NO_ATL_THUNK | | 311 MITIGATION_DEP_NO_ATL_THUNK | |
312 MITIGATION_RELOCATE_IMAGE | | 312 MITIGATION_RELOCATE_IMAGE | |
313 MITIGATION_RELOCATE_IMAGE_REQUIRED | | 313 MITIGATION_RELOCATE_IMAGE_REQUIRED | |
314 MITIGATION_BOTTOM_UP_ASLR | | 314 MITIGATION_BOTTOM_UP_ASLR | |
315 MITIGATION_STRICT_HANDLE_CHECKS | | 315 MITIGATION_STRICT_HANDLE_CHECKS | |
316 MITIGATION_WIN32K_DISABLE | | 316 MITIGATION_WIN32K_DISABLE | |
317 MITIGATION_EXTENSION_DLL_DISABLE | | 317 MITIGATION_EXTENSION_DLL_DISABLE | |
318 MITIGATION_DLL_SEARCH_ORDER)); | 318 MITIGATION_DLL_SEARCH_ORDER)); |
319 } | 319 } |
320 | 320 |
321 bool CanSetProcessMitigationsPreStartup(MitigationFlags flags) { | 321 bool CanSetProcessMitigationsPreStartup(MitigationFlags flags) { |
322 // These mitigations cannot be enabled prior to startup. | 322 // These mitigations cannot be enabled prior to startup. |
323 return !(flags & (MITIGATION_STRICT_HANDLE_CHECKS | | 323 return !(flags & (MITIGATION_STRICT_HANDLE_CHECKS | |
324 MITIGATION_WIN32K_DISABLE | | 324 MITIGATION_WIN32K_DISABLE | |
325 MITIGATION_DLL_SEARCH_ORDER)); | 325 MITIGATION_DLL_SEARCH_ORDER)); |
326 } | 326 } |
327 | 327 |
328 } // namespace sandbox | 328 } // namespace sandbox |
329 | 329 |
OLD | NEW |