From 79e548eb98caefd3ea0f0e4806a7abca6654e7dc Mon Sep 17 00:00:00 2001 From: Chris Palmer Date: Thu, 16 Mar 2017 11:39:48 -0700 Subject: Import PartitionAlloc from Chromium. We'll add callers in a later CL. BUG=pdfium:678 Change-Id: I98c8b2832c4750df326218e24ee8c1bd33b89b50 Reviewed-on: https://pdfium-review.googlesource.com/3066 Commit-Queue: Tom Sepez Reviewed-by: Tom Sepez --- .../address_space_randomization.cc | 132 +++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 third_party/base/allocator/partition_allocator/address_space_randomization.cc (limited to 'third_party/base/allocator/partition_allocator/address_space_randomization.cc') diff --git a/third_party/base/allocator/partition_allocator/address_space_randomization.cc b/third_party/base/allocator/partition_allocator/address_space_randomization.cc new file mode 100644 index 0000000000..fdcc5911b9 --- /dev/null +++ b/third_party/base/allocator/partition_allocator/address_space_randomization.cc @@ -0,0 +1,132 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/base/allocator/partition_allocator/address_space_randomization.h" + +#include "third_party/base/allocator/partition_allocator/page_allocator.h" +#include "third_party/base/allocator/partition_allocator/spin_lock.h" +#include "third_party/build/build_config.h" + +#if defined(OS_WIN) +#include +#else +#include +#include +#endif + +namespace pdfium { +namespace base { + +namespace { + +// This is the same PRNG as used by tcmalloc for mapping address randomness; +// see http://burtleburtle.net/bob/rand/smallprng.html +struct ranctx { + subtle::SpinLock lock; + bool initialized; + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; +}; + +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) + +uint32_t ranvalInternal(ranctx* x) { + uint32_t e = x->a - rot(x->b, 27); + x->a = x->b ^ rot(x->c, 17); + x->b = x->c + x->d; + x->c = x->d + e; + x->d = e + x->a; + return x->d; +} + +#undef rot + +uint32_t ranval(ranctx* x) { + subtle::SpinLock::Guard guard(x->lock); + if (UNLIKELY(!x->initialized)) { + x->initialized = true; + char c; + uint32_t seed = static_cast(reinterpret_cast(&c)); + uint32_t pid; + uint32_t usec; +#if defined(OS_WIN) + pid = GetCurrentProcessId(); + SYSTEMTIME st; + GetSystemTime(&st); + usec = static_cast(st.wMilliseconds * 1000); +#else + pid = static_cast(getpid()); + struct timeval tv; + gettimeofday(&tv, 0); + usec = static_cast(tv.tv_usec); +#endif + seed ^= pid; + seed ^= usec; + x->a = 0xf1ea5eed; + x->b = x->c = x->d = seed; + for (int i = 0; i < 20; ++i) { + (void)ranvalInternal(x); + } + } + uint32_t ret = ranvalInternal(x); + return ret; +} + +static struct ranctx s_ranctx; + +} // namespace + +// Calculates a random preferred mapping address. In calculating an address, we +// balance good ASLR against not fragmenting the address space too badly. +void* GetRandomPageBase() { + uintptr_t random; + random = static_cast(ranval(&s_ranctx)); +#if defined(ARCH_CPU_X86_64) + random <<= 32UL; + random |= static_cast(ranval(&s_ranctx)); +// This address mask gives a low likelihood of address space collisions. We +// handle the situation gracefully if there is a collision. +#if defined(OS_WIN) + // 64-bit Windows has a bizarrely small 8TB user address space. Allocates in + // the 1-5TB region. TODO(palmer): See if Windows >= 8.1 has the full 47 bits, + // and use it if so. crbug.com/672219 + random &= 0x3ffffffffffUL; + random += 0x10000000000UL; +#elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + // This range is copied from the TSan source, but works for all tools. + random &= 0x007fffffffffUL; + random += 0x7e8000000000UL; +#else + // Linux and OS X support the full 47-bit user space of x64 processors. + random &= 0x3fffffffffffUL; +#endif +#elif defined(ARCH_CPU_ARM64) + // ARM64 on Linux has 39-bit user space. + random &= 0x3fffffffffUL; + random += 0x1000000000UL; +#else // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_ARM64) +#if defined(OS_WIN) + // On win32 host systems the randomization plus huge alignment causes + // excessive fragmentation. Plus most of these systems lack ASLR, so the + // randomization isn't buying anything. In that case we just skip it. + // TODO(jschuh): Just dump the randomization when HE-ASLR is present. + static BOOL isWow64 = -1; + if (isWow64 == -1 && !IsWow64Process(GetCurrentProcess(), &isWow64)) + isWow64 = FALSE; + if (!isWow64) + return nullptr; +#endif // defined(OS_WIN) + // This is a good range on Windows, Linux and Mac. + // Allocates in the 0.5-1.5GB region. + random &= 0x3fffffff; + random += 0x20000000; +#endif // defined(ARCH_CPU_X86_64) + random &= kPageAllocationGranularityBaseMask; + return reinterpret_cast(random); +} + +} // namespace base +} // namespace pdfium -- cgit v1.2.3