summaryrefslogtreecommitdiff
path: root/third_party/base/allocator/partition_allocator/address_space_randomization.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/base/allocator/partition_allocator/address_space_randomization.h')
-rw-r--r--third_party/base/allocator/partition_allocator/address_space_randomization.h198
1 files changed, 194 insertions, 4 deletions
diff --git a/third_party/base/allocator/partition_allocator/address_space_randomization.h b/third_party/base/allocator/partition_allocator/address_space_randomization.h
index 97c5f606dd..efad668ebc 100644
--- a/third_party/base/allocator/partition_allocator/address_space_randomization.h
+++ b/third_party/base/allocator/partition_allocator/address_space_randomization.h
@@ -2,17 +2,207 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION
-#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION
+#ifndef THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION_H_
+#define THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION_H_
+
+#include "build/build_config.h"
+#include "third_party/base/allocator/partition_allocator/page_allocator.h"
+#include "third_party/base/base_export.h"
namespace pdfium {
namespace base {
+// Sets the seed for the random number generator used by GetRandomPageBase in
+// order to generate a predictable sequence of addresses. May be called multiple
+// times.
+BASE_EXPORT void SetRandomPageBaseSeed(int64_t seed);
+
// Calculates a random preferred mapping address. In calculating an address, we
// balance good ASLR against not fragmenting the address space too badly.
-void* GetRandomPageBase();
+BASE_EXPORT void* GetRandomPageBase();
+
+namespace internal {
+
+constexpr uintptr_t AslrAddress(uintptr_t mask) {
+ return mask & kPageAllocationGranularityBaseMask;
+}
+constexpr uintptr_t AslrMask(uintptr_t bits) {
+ return AslrAddress((1ULL << bits) - 1ULL);
+}
+
+// Turn off formatting, because the thicket of nested ifdefs below is
+// incomprehensible without indentation. It is also incomprehensible with
+// indentation, but the only other option is a combinatorial explosion of
+// *_{win,linux,mac,foo}_{32,64}.h files.
+//
+// clang-format off
+
+#if defined(ARCH_CPU_64_BITS)
+
+ #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+
+ // We shouldn't allocate system pages at all for sanitizer builds. However,
+ // we do, and if random hint addresses interfere with address ranges
+ // hard-coded in those tools, bad things happen. This address range is
+ // copied from TSAN source but works with all tools. See
+ // https://crbug.com/539863.
+ constexpr uintptr_t kASLRMask = AslrAddress(0x007fffffffffULL);
+ constexpr uintptr_t kASLROffset = AslrAddress(0x7e8000000000ULL);
+
+ #elif defined(OS_WIN)
+
+ // Windows 8.10 and newer support the full 48 bit address range. Older
+ // versions of Windows only support 44 bits. Since kASLROffset is non-zero
+ // and may cause a carry, use 47 and 43 bit masks. See
+ // http://www.alex-ionescu.com/?p=246
+ constexpr uintptr_t kASLRMask = AslrMask(47);
+ constexpr uintptr_t kASLRMaskBefore8_10 = AslrMask(43);
+ // Try not to map pages into the range where Windows loads DLLs by default.
+ constexpr uintptr_t kASLROffset = 0x80000000ULL;
+
+ #elif defined(OS_MACOSX)
+
+ // macOS as of 10.12.5 does not clean up entries in page map levels 3/4
+ // [PDP/PML4] created from mmap or mach_vm_allocate, even after the region
+ // is destroyed. Using a virtual address space that is too large causes a
+ // leak of about 1 wired [can never be paged out] page per call to mmap. The
+ // page is only reclaimed when the process is killed. Confine the hint to a
+ // 39-bit section of the virtual address space.
+ //
+ // This implementation adapted from
+ // https://chromium-review.googlesource.com/c/v8/v8/+/557958. The difference
+ // is that here we clamp to 39 bits, not 32.
+ //
+ // TODO(crbug.com/738925): Remove this limitation if/when the macOS behavior
+ // changes.
+ constexpr uintptr_t kASLRMask = AslrMask(38);
+ constexpr uintptr_t kASLROffset = AslrAddress(0x1000000000ULL);
+
+ #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+
+ #if defined(ARCH_CPU_X86_64)
+
+ // Linux (and macOS) support the full 47-bit user space of x64 processors.
+ // Use only 46 to allow the kernel a chance to fulfill the request.
+ constexpr uintptr_t kASLRMask = AslrMask(46);
+ constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+ #elif defined(ARCH_CPU_ARM64)
+
+ #if defined(OS_ANDROID)
+
+ // Restrict the address range on Android to avoid a large performance
+ // regression in single-process WebViews. See https://crbug.com/837640.
+ constexpr uintptr_t kASLRMask = AslrMask(30);
+ constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
+
+ #else
+
+ // ARM64 on Linux has 39-bit user space. Use 38 bits since kASLROffset
+ // could cause a carry.
+ constexpr uintptr_t kASLRMask = AslrMask(38);
+ constexpr uintptr_t kASLROffset = AslrAddress(0x1000000000ULL);
+
+ #endif
+
+ #elif defined(ARCH_CPU_PPC64)
+
+ #if defined(OS_AIX)
+
+ // AIX has 64 bits of virtual addressing, but we limit the address range
+ // to (a) minimize segment lookaside buffer (SLB) misses; and (b) use
+ // extra address space to isolate the mmap regions.
+ constexpr uintptr_t kASLRMask = AslrMask(30);
+ constexpr uintptr_t kASLROffset = AslrAddress(0x400000000000ULL);
+
+ #elif defined(ARCH_CPU_BIG_ENDIAN)
+
+ // Big-endian Linux PPC has 44 bits of virtual addressing. Use 42.
+ constexpr uintptr_t kASLRMask = AslrMask(42);
+ constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+ #else // !defined(OS_AIX) && !defined(ARCH_CPU_BIG_ENDIAN)
+
+ // Little-endian Linux PPC has 48 bits of virtual addressing. Use 46.
+ constexpr uintptr_t kASLRMask = AslrMask(46);
+ constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+ #endif // !defined(OS_AIX) && !defined(ARCH_CPU_BIG_ENDIAN)
+
+ #elif defined(ARCH_CPU_S390X)
+
+ // Linux on Z uses bits 22 - 32 for Region Indexing, which translates to
+ // 42 bits of virtual addressing. Truncate to 40 bits to allow kernel a
+ // chance to fulfill the request.
+ constexpr uintptr_t kASLRMask = AslrMask(40);
+ constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+ #elif defined(ARCH_CPU_S390)
+
+ // 31 bits of virtual addressing. Truncate to 29 bits to allow the kernel
+ // a chance to fulfill the request.
+ constexpr uintptr_t kASLRMask = AslrMask(29);
+ constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+ #else // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_PPC64) &&
+ // !defined(ARCH_CPU_S390X) && !defined(ARCH_CPU_S390)
+
+ // For all other POSIX variants, use 30 bits.
+ constexpr uintptr_t kASLRMask = AslrMask(30);
+
+ #if defined(OS_SOLARIS)
+
+ // For our Solaris/illumos mmap hint, we pick a random address in the
+ // bottom half of the top half of the address space (that is, the third
+ // quarter). Because we do not MAP_FIXED, this will be treated only as a
+ // hint -- the system will not fail to mmap because something else
+ // happens to already be mapped at our random address. We deliberately
+ // set the hint high enough to get well above the system's break (that
+ // is, the heap); Solaris and illumos will try the hint and if that
+ // fails allocate as if there were no hint at all. The high hint
+ // prevents the break from getting hemmed in at low values, ceding half
+ // of the address space to the system heap.
+ constexpr uintptr_t kASLROffset = AslrAddress(0x80000000ULL);
+
+ #elif defined(OS_AIX)
+
+ // The range 0x30000000 - 0xD0000000 is available on AIX; choose the
+ // upper range.
+ constexpr uintptr_t kASLROffset = AslrAddress(0x90000000ULL);
+
+ #else // !defined(OS_SOLARIS) && !defined(OS_AIX)
+
+ // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
+ // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macOS
+ // 10.6 and 10.7.
+ constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
+
+ #endif // !defined(OS_SOLARIS) && !defined(OS_AIX)
+
+ #endif // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_PPC64) &&
+ // !defined(ARCH_CPU_S390X) && !defined(ARCH_CPU_S390)
+
+ #endif // defined(OS_POSIX)
+
+#elif defined(ARCH_CPU_32_BITS)
+
+ // This is a good range on 32-bit Windows and Android (the only platforms on
+ // which we support 32-bitness). Allocates in the 0.5 - 1.5 GiB region. There
+ // is no issue with carries here.
+ constexpr uintptr_t kASLRMask = AslrMask(30);
+ constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
+
+#else
+
+ #error Please tell us about your exotic hardware! Sounds interesting.
+
+#endif // defined(ARCH_CPU_32_BITS)
+
+// clang-format on
+
+} // namespace internal
} // namespace base
} // namespace pdfium
-#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION
+#endif // THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_SPACE_RANDOMIZATION_H_