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" | |
9 #include "sandbox/win/src/sandbox_utils.h" | 10 #include "sandbox/win/src/sandbox_utils.h" |
11 #include "sandbox/win/src/target_process.h" | |
10 #include "sandbox/win/src/win_utils.h" | 12 #include "sandbox/win/src/win_utils.h" |
11 | 13 |
12 namespace { | 14 namespace { |
13 | 15 |
14 // Functions for enabling policies. | 16 // Functions for enabling policies. |
15 typedef BOOL (WINAPI *SetProcessDEPPolicyFunction)(DWORD dwFlags); | 17 typedef BOOL (WINAPI *SetProcessDEPPolicyFunction)(DWORD dwFlags); |
16 | 18 |
17 typedef BOOL (WINAPI *SetProcessMitigationPolicyFunction)( | 19 typedef BOOL (WINAPI *SetProcessMitigationPolicyFunction)( |
18 PROCESS_MITIGATION_POLICY mitigation_policy, | 20 PROCESS_MITIGATION_POLICY mitigation_policy, |
19 PVOID buffer, | 21 PVOID buffer, |
20 SIZE_T length); | 22 SIZE_T length); |
21 | 23 |
22 typedef BOOL (WINAPI *SetDefaultDllDirectoriesFunction)( | 24 typedef BOOL (WINAPI *SetDefaultDllDirectoriesFunction)( |
23 DWORD DirectoryFlags); | 25 DWORD DirectoryFlags); |
24 | 26 |
27 void CALLBACK ApplyMitigationsCallback(ULONG_PTR flags) { | |
28 if (!sandbox::ApplyProcessMitigationsToCurrentProcess(flags)) | |
29 ::TerminateProcess(::GetCurrentProcess(), sandbox::SBOX_FATAL_MITIGATION); | |
30 } | |
31 | |
25 } // namespace | 32 } // namespace |
26 | 33 |
27 namespace sandbox { | 34 namespace sandbox { |
28 | 35 |
29 bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags) { | 36 bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags) { |
30 if (!CanSetProcessMitigationsPostStartup(flags)) | 37 if (!CanSetProcessMitigationsPostStartup(flags)) |
31 return false; | 38 return false; |
32 | 39 |
33 // We can't apply anything before Win XP, so just return cleanly. | 40 // We can't apply anything before Win XP, so just return cleanly. |
34 if (!IsXPSP2OrLater()) | 41 if (!IsXPSP2OrLater()) |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON; | 237 PROCESS_CREATION_MITIGATION_POLICY_WIN32K_SYSTEM_CALL_DISABLE_ALWAYS_ON; |
231 } | 238 } |
232 | 239 |
233 if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { | 240 if (flags & MITIGATION_EXTENSION_DLL_DISABLE) { |
234 *policy_flags |= | 241 *policy_flags |= |
235 PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; | 242 PROCESS_CREATION_MITIGATION_POLICY_EXTENSION_POINT_DISABLE_ALWAYS_ON; |
236 } | 243 } |
237 } | 244 } |
238 | 245 |
239 MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags) { | 246 MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags) { |
240 // Anything prior to XP SP2. | 247 base::win::Version version = base::win::GetVersion(); |
241 if (!IsXPSP2OrLater()) | 248 |
249 if (version < base::win::VERSION_VISTA) { | |
242 return 0; | 250 return 0; |
243 | 251 |
244 base::win::Version version = base::win::GetVersion(); | |
245 | |
246 // Windows XP SP2+. | |
247 if (version < base::win::VERSION_VISTA) { | |
248 return flags & (MITIGATION_DEP | | |
249 MITIGATION_DEP_NO_ATL_THUNK); | |
250 | |
251 // Windows Vista | |
252 if (version < base::win::VERSION_WIN7) { | |
253 return flags & (MITIGATION_DEP | | |
254 MITIGATION_DEP_NO_ATL_THUNK | | |
255 MITIGATION_BOTTOM_UP_ASLR | | |
rvargas (doing something else)
2012/10/03 02:42:37
Are you losing these?
jschuh
2012/10/03 03:00:06
No. The DEP flags don't need to be passed due to t
| |
256 MITIGATION_DLL_SEARCH_ORDER | | |
257 MITIGATION_HEAP_TERMINATE); | |
258 } | |
259 | |
260 // Windows 7 and Vista. | |
261 } else if (version < base::win::VERSION_WIN8) { | 252 } else if (version < base::win::VERSION_WIN8) { |
262 return flags & (MITIGATION_BOTTOM_UP_ASLR | | 253 return flags & (MITIGATION_DLL_SEARCH_ORDER | |
263 MITIGATION_DLL_SEARCH_ORDER | | |
264 MITIGATION_HEAP_TERMINATE); | 254 MITIGATION_HEAP_TERMINATE); |
265 } | 255 } |
266 | 256 |
267 // Windows 8 and above. | 257 // Windows 8 and above. |
268 return flags & (MITIGATION_BOTTOM_UP_ASLR | | 258 return flags & (MITIGATION_DLL_SEARCH_ORDER); |
269 MITIGATION_DLL_SEARCH_ORDER); | |
270 } | 259 } |
271 | 260 |
272 bool ApplyProcessMitigationsToSuspendedProcess(HANDLE process, | 261 bool ApplyProcessMitigationsToSuspendedTarget(TargetProcess* target, |
273 MitigationFlags flags) { | 262 MitigationFlags flags) { |
274 // This is a hack to fake a weak bottom-up ASLR on 32-bit Windows. | |
275 #if !defined(_WIN64) | 263 #if !defined(_WIN64) |
264 // This is a hack to fake a weak bottom-up ASLR on 32-bit Windows. | |
276 if (flags & MITIGATION_BOTTOM_UP_ASLR) { | 265 if (flags & MITIGATION_BOTTOM_UP_ASLR) { |
277 unsigned int limit; | 266 unsigned int limit; |
278 rand_s(&limit); | 267 rand_s(&limit); |
279 char* ptr = 0; | 268 char* ptr = 0; |
280 const size_t kMask64k = 0xFFFF; | 269 const size_t kMask64k = 0xFFFF; |
281 // Random range (512k-16.5mb) in 64k steps. | 270 // Random range (512k-16.5mb) in 64k steps. |
282 const char* end = ptr + ((((limit % 16384) + 512) * 1024) & ~kMask64k); | 271 const char* end = ptr + ((((limit % 16384) + 512) * 1024) & ~kMask64k); |
272 HANDLE process = target->Process(); | |
283 while (ptr < end) { | 273 while (ptr < end) { |
284 MEMORY_BASIC_INFORMATION memory_info; | 274 MEMORY_BASIC_INFORMATION memory_info; |
285 if (!::VirtualQueryEx(process, ptr, &memory_info, sizeof(memory_info))) | 275 if (!::VirtualQueryEx(process, ptr, &memory_info, sizeof(memory_info))) |
286 break; | 276 break; |
287 size_t size = std::min((memory_info.RegionSize + kMask64k) & ~kMask64k, | 277 size_t size = std::min((memory_info.RegionSize + kMask64k) & ~kMask64k, |
288 static_cast<SIZE_T>(end - ptr)); | 278 static_cast<SIZE_T>(end - ptr)); |
289 if (ptr && memory_info.State == MEM_FREE) | 279 if (ptr && memory_info.State == MEM_FREE) |
290 ::VirtualAllocEx(process, ptr, size, MEM_RESERVE, PAGE_NOACCESS); | 280 ::VirtualAllocEx(process, ptr, size, MEM_RESERVE, PAGE_NOACCESS); |
291 ptr += size; | 281 ptr += size; |
292 } | 282 } |
293 } | 283 } |
284 | |
285 // Since the process is suspended, we can schedule an APC to set the DEP | |
286 // policy immediately after then loader finishes. | |
rvargas (doing something else)
2012/10/03 02:42:37
nit: the loader
jschuh
2012/10/03 03:00:06
Done.
| |
287 ULONG_PTR dep_flags = flags & (MITIGATION_DEP | MITIGATION_DEP_NO_ATL_THUNK); | |
288 if (dep_flags && base::win::GetVersion() < base::win::VERSION_WIN7) { | |
289 if (!::QueueUserAPC(ApplyMitigationsCallback, target->MainThread(), | |
rvargas (doing something else)
2012/10/03 02:42:37
I'm not fully convinced that this is a good idea,
jschuh
2012/10/03 03:00:06
That's pretty much it. I want to do it before we e
rvargas (doing something else)
2012/10/03 22:23:57
But the bulk of the benefit is by protecting pages
rvargas (doing something else)
2012/10/11 23:04:44
btw, this breaks with the SANDBOX_EXPORTS mode, bu
| |
290 static_cast<ULONG_PTR>(dep_flags))) { | |
291 return false; | |
292 } | |
293 } | |
294 #endif | 294 #endif |
295 | 295 |
296 return true; | 296 return true; |
297 } | 297 } |
298 | 298 |
299 bool CanSetProcessMitigationsPostStartup(MitigationFlags flags) { | 299 bool CanSetProcessMitigationsPostStartup(MitigationFlags flags) { |
300 // All of these mitigations can be enabled after startup. | 300 // All of these mitigations can be enabled after startup. |
301 return !(flags & ~(MITIGATION_HEAP_TERMINATE | | 301 return !(flags & ~(MITIGATION_HEAP_TERMINATE | |
302 MITIGATION_DEP | | 302 MITIGATION_DEP | |
303 MITIGATION_DEP_NO_ATL_THUNK | | 303 MITIGATION_DEP_NO_ATL_THUNK | |
304 MITIGATION_RELOCATE_IMAGE | | 304 MITIGATION_RELOCATE_IMAGE | |
305 MITIGATION_RELOCATE_IMAGE_REQUIRED | | 305 MITIGATION_RELOCATE_IMAGE_REQUIRED | |
306 MITIGATION_BOTTOM_UP_ASLR | | 306 MITIGATION_BOTTOM_UP_ASLR | |
307 MITIGATION_STRICT_HANDLE_CHECKS | | 307 MITIGATION_STRICT_HANDLE_CHECKS | |
308 MITIGATION_WIN32K_DISABLE | | 308 MITIGATION_WIN32K_DISABLE | |
309 MITIGATION_EXTENSION_DLL_DISABLE | | 309 MITIGATION_EXTENSION_DLL_DISABLE | |
310 MITIGATION_DLL_SEARCH_ORDER)); | 310 MITIGATION_DLL_SEARCH_ORDER)); |
311 } | 311 } |
312 | 312 |
313 bool CanSetProcessMitigationsPreStartup(MitigationFlags flags) { | 313 bool CanSetProcessMitigationsPreStartup(MitigationFlags flags) { |
314 // These mitigations cannot be enabled prior to startup. | 314 // These mitigations cannot be enabled prior to startup. |
315 return !(flags & (MITIGATION_STRICT_HANDLE_CHECKS | | 315 return !(flags & (MITIGATION_STRICT_HANDLE_CHECKS | |
316 MITIGATION_WIN32K_DISABLE | | 316 MITIGATION_WIN32K_DISABLE | |
317 MITIGATION_DLL_SEARCH_ORDER)); | 317 MITIGATION_DLL_SEARCH_ORDER)); |
318 } | 318 } |
319 | 319 |
320 } // namespace sandbox | 320 } // namespace sandbox |
321 | 321 |
OLD | NEW |