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