-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path58f23ffbd4a5688882be72acc96c39d0c109a6d4.diff
152 lines (139 loc) · 6.44 KB
/
58f23ffbd4a5688882be72acc96c39d0c109a6d4.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
diff --git a/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.cc b/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.cc
index 1a9aff75b88bf..682dfde5fea6a 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.cc
@@ -10,7 +10,9 @@
#include "partition_alloc/random.h"
#if PA_BUILDFLAG(IS_WIN)
-#include <windows.h>
+#include <windows.h> // Must be in front of other Windows header files.
+
+#include <versionhelpers.h>
#endif
namespace partition_alloc {
@@ -22,10 +24,26 @@ uintptr_t GetRandomPageBase() {
random <<= 32ULL;
random |= static_cast<uintptr_t>(internal::RandomValue());
- // The ASLRMask() and ASLROffset() constants will be suitable for the
- // OS and build configuration.
+// The ASLRMask() and ASLROffset() constants will be suitable for the
+// OS and build configuration.
+#if PA_BUILDFLAG(IS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+ // Windows >= 8.1 has the full 47 bits. Use them where available.
+ static bool windows_81 = false;
+ static bool windows_81_initialized = false;
+ if (!windows_81_initialized) {
+ windows_81 = IsWindows8Point1OrGreater();
+ windows_81_initialized = true;
+ }
+ if (!windows_81) {
+ random &= internal::ASLRMaskBefore8_10();
+ } else {
+ random &= internal::ASLRMask();
+ }
+ random += internal::ASLROffset();
+#else
random &= internal::ASLRMask();
random += internal::ASLROffset();
+#endif // PA_BUILDFLAG(IS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
#else // PA_BUILDFLAG(HAS_64_BIT_POINTERS)
#if PA_BUILDFLAG(IS_WIN)
// On win32 host systems the randomization plus huge alignment causes
diff --git a/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.h b/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.h
index 5e28dfc9a2819..4ac7d7015d8a6 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization.h
@@ -56,12 +56,16 @@ AslrMask(uintptr_t bits) {
#elif PA_BUILDFLAG(IS_WIN)
- // Windows 8.10 and newer support the full 48 bit address range. Since
- // ASLROffset() is non-zero and may cause a carry, use 47 bit masks. See
+ // Windows 8.10 and newer support the full 48 bit address range. Older
+ // versions of Windows only support 44 bits. Since ASLROffset() is non-zero
+ // and may cause a carry, use 47 and 43 bit masks. See
// http://www.alex-ionescu.com/?p=246
PA_ALWAYS_INLINE constexpr uintptr_t ASLRMask() {
return AslrMask(47);
}
+ PA_ALWAYS_INLINE constexpr uintptr_t ASLRMaskBefore8_10() {
+ return AslrMask(43);
+ }
// Try not to map pages into the range where Windows loads DLLs by default.
PA_ALWAYS_INLINE constexpr uintptr_t ASLROffset() {
return 0x80000000ULL;
diff --git a/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization_unittest.cc
index cb920da0da495..83f4ff97c86fc 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/address_space_randomization_unittest.cc
@@ -17,4 +17,6 @@
#include <windows.h>
+// versionhelpers.h must be included after windows.h.
+#include <versionhelpers.h>
#endif
namespace partition_alloc {
@@ -26,6 +28,12 @@ namespace {
uintptr_t GetMask() {
uintptr_t mask = internal::ASLRMask();
#if PA_BUILDFLAG(PA_ARCH_CPU_64_BITS)
+// Sanitizers use their own ASLR mask constant.
+#if PA_BUILDFLAG(IS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+ if (!IsWindows8Point1OrGreater()) {
+ mask = internal::ASLRMaskBefore8_10();
+ }
+#endif // PA_BUILDFLAG(IS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR))
#elif PA_BUILDFLAG(PA_ARCH_CPU_32_BITS)
#if PA_BUILDFLAG(IS_WIN)
BOOL is_wow64 = FALSE;
diff --git a/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_win.h b/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_win.h
index 44ef45c3e325f..7bfc062b66a25 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_win.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_win.h
@@ -5,5 +5,7 @@
#ifndef PARTITION_ALLOC_PAGE_ALLOCATOR_INTERNALS_WIN_H_
#define PARTITION_ALLOC_PAGE_ALLOCATOR_INTERNALS_WIN_H_
+#include <versionhelpers.h>
+
#include <cstdint>
@@ -16,6 +18,17 @@
namespace partition_alloc::internal {
+namespace {
+
+// On Windows, discarded pages are not returned to the system immediately and
+// not guaranteed to be zeroed when returned to the application.
+using DiscardVirtualMemoryFunction = DWORD(WINAPI*)(PVOID virtualAddress,
+ SIZE_T size);
+DiscardVirtualMemoryFunction s_discard_virtual_memory =
+ reinterpret_cast<DiscardVirtualMemoryFunction>(-1);
+
+} // namespace
+
// |VirtualAlloc| will fail if allocation at the hint address is blocked.
constexpr bool kHintIsAdvisory = false;
std::atomic<int32_t> s_allocPageErrorCode{ERROR_SUCCESS};
@@ -226,10 +239,27 @@ bool TryRecommitSystemPagesInternal(
}
void DiscardSystemPagesInternal(uintptr_t address, size_t length) {
+ if (s_discard_virtual_memory ==
+ reinterpret_cast<DiscardVirtualMemoryFunction>(-1)) {
+ // DiscardVirtualMemory's minimum supported client is Windows 8.1 Update.
+ // So skip GetProcAddress("DiscardVirtualMemory") if windows version is
+ // smaller than Windows 8.1.
+ if (IsWindows8Point1OrGreater()) {
+ s_discard_virtual_memory =
+ reinterpret_cast<DiscardVirtualMemoryFunction>(GetProcAddress(
+ GetModuleHandle(L"Kernel32.dll"), "DiscardVirtualMemory"));
+ } else {
+ s_discard_virtual_memory = nullptr;
+ }
+ }
+
void* ptr = reinterpret_cast<void*>(address);
// Use DiscardVirtualMemory when available because it releases faster than
// MEM_RESET.
- DWORD ret = DiscardVirtualMemory(ptr, length);
+ DWORD ret = 1;
+ if (s_discard_virtual_memory) {
+ ret = s_discard_virtual_memory(ptr, length);
+ }
// DiscardVirtualMemory is buggy in Win10 SP0, so fall back to MEM_RESET on
// failure.
if (ret) {