| 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 |