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
3 // found in the LICENSE file.
4
5 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION_H_
6 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION_H_
7
8 #include "base/allocator/partition_allocator/page_allocator.h"
9 #include "base/base_export.h"
10 #include "build/build_config.h"
11
12 namespace base {
13
14 // Calculates a random preferred mapping address. In calculating an address, we
15 // balance good ASLR against not fragmenting the address space too badly.
16 BASE_EXPORT void* GetRandomPageBase();
17
18 namespace internal {
19
AslrAddress(uintptr_t mask)20 constexpr uintptr_t AslrAddress(uintptr_t mask) {
21 return mask & kPageAllocationGranularityBaseMask;
22 }
AslrMask(uintptr_t bits)23 constexpr uintptr_t AslrMask(uintptr_t bits) {
24 return AslrAddress((1ULL << bits) - 1ULL);
25 }
26
27 // Turn off formatting, because the thicket of nested ifdefs below is
28 // incomprehensible without indentation. It is also incomprehensible with
29 // indentation, but the only other option is a combinatorial explosion of
30 // *_{win,linux,mac,foo}_{32,64}.h files.
31 //
32 // clang-format off
33
34 #if defined(ARCH_CPU_64_BITS)
35
36 #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
37
38 // We shouldn't allocate system pages at all for sanitizer builds. However,
39 // we do, and if random hint addresses interfere with address ranges
40 // hard-coded in those tools, bad things happen. This address range is
41 // copied from TSAN source but works with all tools. See
42 // https://crbug.com/539863.
43 constexpr uintptr_t kASLRMask = AslrAddress(0x007fffffffffULL);
44 constexpr uintptr_t kASLROffset = AslrAddress(0x7e8000000000ULL);
45
46 #elif defined(OS_WIN)
47
48 // Windows 8.10 and newer support the full 48 bit address range. Older
49 // versions of Windows only support 44 bits. Since kASLROffset is non-zero
50 // and may cause a carry, use 47 and 43 bit masks. See
51 // http://www.alex-ionescu.com/?p=246
52 constexpr uintptr_t kASLRMask = AslrMask(47);
53 constexpr uintptr_t kASLRMaskBefore8_10 = AslrMask(43);
54 // Try not to map pages into the range where Windows loads DLLs by default.
55 constexpr uintptr_t kASLROffset = 0x80000000ULL;
56
57 #elif defined(OS_MACOSX)
58
59 // macOS as of 10.12.5 does not clean up entries in page map levels 3/4
60 // [PDP/PML4] created from mmap or mach_vm_allocate, even after the region
61 // is destroyed. Using a virtual address space that is too large causes a
62 // leak of about 1 wired [can never be paged out] page per call to mmap. The
63 // page is only reclaimed when the process is killed. Confine the hint to a
64 // 39-bit section of the virtual address space.
65 //
66 // This implementation adapted from
67 // https://chromium-review.googlesource.com/c/v8/v8/+/557958. The difference
68 // is that here we clamp to 39 bits, not 32.
69 //
70 // TODO(crbug.com/738925): Remove this limitation if/when the macOS behavior
71 // changes.
72 constexpr uintptr_t kASLRMask = AslrMask(38);
73 constexpr uintptr_t kASLROffset = AslrAddress(0x1000000000ULL);
74
75 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
76
77 #if defined(ARCH_CPU_X86_64)
78
79 // Linux (and macOS) support the full 47-bit user space of x64 processors.
80 // Use only 46 to allow the kernel a chance to fulfill the request.
81 constexpr uintptr_t kASLRMask = AslrMask(46);
82 constexpr uintptr_t kASLROffset = AslrAddress(0);
83
84 #elif defined(ARCH_CPU_ARM64)
85
86 #if defined(OS_ANDROID)
87
88 // Restrict the address range on Android to avoid a large performance
89 // regression in single-process WebViews. See https://crbug.com/837640.
90 constexpr uintptr_t kASLRMask = AslrMask(30);
91 constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
92
93 #else
94
95 // ARM64 on Linux has 39-bit user space. Use 38 bits since kASLROffset
96 // could cause a carry.
97 constexpr uintptr_t kASLRMask = AslrMask(38);
98 constexpr uintptr_t kASLROffset = AslrAddress(0x1000000000ULL);
99
100 #endif
101
102 #elif defined(ARCH_CPU_PPC64)
103
104 #if defined(OS_AIX)
105
106 // AIX has 64 bits of virtual addressing, but we limit the address range
107 // to (a) minimize segment lookaside buffer (SLB) misses; and (b) use
108 // extra address space to isolate the mmap regions.
109 constexpr uintptr_t kASLRMask = AslrMask(30);
110 constexpr uintptr_t kASLROffset = AslrAddress(0x400000000000ULL);
111
112 #elif defined(ARCH_CPU_BIG_ENDIAN)
113
114 // Big-endian Linux PPC has 44 bits of virtual addressing. Use 42.
115 constexpr uintptr_t kASLRMask = AslrMask(42);
116 constexpr uintptr_t kASLROffset = AslrAddress(0);
117
118 #else // !defined(OS_AIX) && !defined(ARCH_CPU_BIG_ENDIAN)
119
120 // Little-endian Linux PPC has 48 bits of virtual addressing. Use 46.
121 constexpr uintptr_t kASLRMask = AslrMask(46);
122 constexpr uintptr_t kASLROffset = AslrAddress(0);
123
124 #endif // !defined(OS_AIX) && !defined(ARCH_CPU_BIG_ENDIAN)
125
126 #elif defined(ARCH_CPU_S390X)
127
128 // Linux on Z uses bits 22 - 32 for Region Indexing, which translates to
129 // 42 bits of virtual addressing. Truncate to 40 bits to allow kernel a
130 // chance to fulfill the request.
131 constexpr uintptr_t kASLRMask = AslrMask(40);
132 constexpr uintptr_t kASLROffset = AslrAddress(0);
133
134 #elif defined(ARCH_CPU_S390)
135
136 // 31 bits of virtual addressing. Truncate to 29 bits to allow the kernel
137 // a chance to fulfill the request.
138 constexpr uintptr_t kASLRMask = AslrMask(29);
139 constexpr uintptr_t kASLROffset = AslrAddress(0);
140
141 #else // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_PPC64) &&
142 // !defined(ARCH_CPU_S390X) && !defined(ARCH_CPU_S390)
143
144 // For all other POSIX variants, use 30 bits.
145 constexpr uintptr_t kASLRMask = AslrMask(30);
146
147 #if defined(OS_SOLARIS)
148
149 // For our Solaris/illumos mmap hint, we pick a random address in the
150 // bottom half of the top half of the address space (that is, the third
151 // quarter). Because we do not MAP_FIXED, this will be treated only as a
152 // hint -- the system will not fail to mmap because something else
153 // happens to already be mapped at our random address. We deliberately
154 // set the hint high enough to get well above the system's break (that
155 // is, the heap); Solaris and illumos will try the hint and if that
156 // fails allocate as if there were no hint at all. The high hint
157 // prevents the break from getting hemmed in at low values, ceding half
158 // of the address space to the system heap.
159 constexpr uintptr_t kASLROffset = AslrAddress(0x80000000ULL);
160
161 #elif defined(OS_AIX)
162
163 // The range 0x30000000 - 0xD0000000 is available on AIX; choose the
164 // upper range.
165 constexpr uintptr_t kASLROffset = AslrAddress(0x90000000ULL);
166
167 #else // !defined(OS_SOLARIS) && !defined(OS_AIX)
168
169 // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
170 // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macOS
171 // 10.6 and 10.7.
172 constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
173
174 #endif // !defined(OS_SOLARIS) && !defined(OS_AIX)
175
176 #endif // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_PPC64) &&
177 // !defined(ARCH_CPU_S390X) && !defined(ARCH_CPU_S390)
178
179 #endif // defined(OS_POSIX)
180
181 #elif defined(ARCH_CPU_32_BITS)
182
183 // This is a good range on 32-bit Windows and Android (the only platforms on
184 // which we support 32-bitness). Allocates in the 0.5 - 1.5 GiB region. There
185 // is no issue with carries here.
186 constexpr uintptr_t kASLRMask = AslrMask(30);
187 constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
188
189 #else
190
191 #error Please tell us about your exotic hardware! Sounds interesting.
192
193 #endif // defined(ARCH_CPU_32_BITS)
194
195 // clang-format on
196
197 } // namespace internal
198
199 } // namespace base
200
201 #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION_H_
202