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 #include "third_party/base/allocator/partition_allocator/address_space_randomization.h"
6 
7 #include "build/build_config.h"
8 #include "third_party/base/allocator/partition_allocator/page_allocator.h"
9 #include "third_party/base/allocator/partition_allocator/random.h"
10 #include "third_party/base/allocator/partition_allocator/spin_lock.h"
11 #include "third_party/base/check_op.h"
12 
13 #if defined(OS_WIN)
14 #include <windows.h>  // Must be in front of other Windows header files.
15 
16 #include <VersionHelpers.h>
17 #endif
18 
19 namespace pdfium {
20 namespace base {
21 
GetRandomPageBase()22 void* GetRandomPageBase() {
23   uintptr_t random = static_cast<uintptr_t>(RandomValue());
24 
25 #if defined(ARCH_CPU_64_BITS)
26   random <<= 32ULL;
27   random |= static_cast<uintptr_t>(RandomValue());
28 
29 // The kASLRMask and kASLROffset constants will be suitable for the
30 // OS and build configuration.
31 #if defined(OS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
32   // Windows >= 8.1 has the full 47 bits. Use them where available.
33   static bool windows_81 = false;
34   static bool windows_81_initialized = false;
35   if (!windows_81_initialized) {
36     windows_81 = IsWindows8Point1OrGreater();
37     windows_81_initialized = true;
38   }
39   if (!windows_81) {
40     random &= internal::ASLRMaskBefore8_10();
41   } else {
42     random &= internal::ASLRMask();
43   }
44   random += internal::ASLROffset();
45 #else
46   random &= internal::ASLRMask();
47   random += internal::ASLROffset();
48 #endif  // defined(OS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
49 #else   // defined(ARCH_CPU_32_BITS)
50 #if defined(OS_WIN)
51   // On win32 host systems the randomization plus huge alignment causes
52   // excessive fragmentation. Plus most of these systems lack ASLR, so the
53   // randomization isn't buying anything. In that case we just skip it.
54   // TODO(palmer): Just dump the randomization when HE-ASLR is present.
55   static BOOL is_wow64 = -1;
56   if (is_wow64 == -1 && !IsWow64Process(GetCurrentProcess(), &is_wow64))
57     is_wow64 = FALSE;
58   if (!is_wow64)
59     return nullptr;
60 #endif  // defined(OS_WIN)
61   random &= internal::ASLRMask();
62   random += internal::ASLROffset();
63 #endif  // defined(ARCH_CPU_32_BITS)
64 
65   DCHECK_EQ(0ULL, (random & PageAllocationGranularityOffsetMask()));
66   return reinterpret_cast<void*>(random);
67 }
68 
69 }  // namespace base
70 }  // namespace pdfium
71