• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018 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_PARTITION_FREELIST_ENTRY_H_
6 #define THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_FREELIST_ENTRY_H_
7 
8 #include <stdint.h>
9 
10 #include "build/build_config.h"
11 #include "third_party/base/allocator/partition_allocator/partition_alloc_constants.h"
12 #include "third_party/base/compiler_specific.h"
13 #include "third_party/base/sys_byteorder.h"
14 
15 namespace pdfium {
16 namespace base {
17 namespace internal {
18 
19 struct EncodedPartitionFreelistEntry;
20 
21 struct PartitionFreelistEntry {
22   EncodedPartitionFreelistEntry* next;
23 
24   PartitionFreelistEntry() = delete;
25   ~PartitionFreelistEntry() = delete;
26 
EncodePartitionFreelistEntry27   ALWAYS_INLINE static EncodedPartitionFreelistEntry* Encode(
28       PartitionFreelistEntry* ptr) {
29     return reinterpret_cast<EncodedPartitionFreelistEntry*>(Transform(ptr));
30   }
31 
32  private:
33   friend struct EncodedPartitionFreelistEntry;
TransformPartitionFreelistEntry34   static ALWAYS_INLINE void* Transform(void* ptr) {
35     // We use bswap on little endian as a fast mask for two reasons:
36     // 1) If an object is freed and its vtable used where the attacker doesn't
37     // get the chance to run allocations between the free and use, the vtable
38     // dereference is likely to fault.
39     // 2) If the attacker has a linear buffer overflow and elects to try and
40     // corrupt a freelist pointer, partial pointer overwrite attacks are
41     // thwarted.
42     // For big endian, similar guarantees are arrived at with a negation.
43 #if defined(ARCH_CPU_BIG_ENDIAN)
44     uintptr_t masked = ~reinterpret_cast<uintptr_t>(ptr);
45 #else
46     uintptr_t masked = ByteSwapUintPtrT(reinterpret_cast<uintptr_t>(ptr));
47 #endif
48     return reinterpret_cast<void*>(masked);
49   }
50 };
51 
52 struct EncodedPartitionFreelistEntry {
53   char scrambled[sizeof(PartitionFreelistEntry*)];
54 
55   EncodedPartitionFreelistEntry() = delete;
56   ~EncodedPartitionFreelistEntry() = delete;
57 
DecodeEncodedPartitionFreelistEntry58   ALWAYS_INLINE static PartitionFreelistEntry* Decode(
59       EncodedPartitionFreelistEntry* ptr) {
60     return reinterpret_cast<PartitionFreelistEntry*>(
61         PartitionFreelistEntry::Transform(ptr));
62   }
63 };
64 
65 static_assert(sizeof(PartitionFreelistEntry) ==
66                   sizeof(EncodedPartitionFreelistEntry),
67               "Should not have padding");
68 
69 }  // namespace internal
70 }  // namespace base
71 }  // namespace pdfium
72 
73 #endif  // THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_FREELIST_ENTRY_H_
74