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