1 // Copyright 2021 The Chromium Authors 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 BASE_MEMORY_NONSCANNABLE_MEMORY_H_ 6 #define BASE_MEMORY_NONSCANNABLE_MEMORY_H_ 7 8 #include <cstdint> 9 10 #include <atomic> 11 #include <memory> 12 13 #include "base/allocator/partition_allocator/partition_alloc_buildflags.h" 14 #include "base/base_export.h" 15 #include "base/no_destructor.h" 16 17 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 18 #include "base/allocator/partition_allocator/partition_alloc.h" 19 20 #if BUILDFLAG(USE_STARSCAN) 21 #include "base/allocator/partition_allocator/starscan/metadata_allocator.h" 22 #endif 23 #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 24 25 // This file contains allocation/deallocation functions for memory that doesn't 26 // need to be scanned by PCScan. Such memory should only contain "data" objects, 27 // i.e. objects that don't have pointers/references to other objects. An example 28 // would be strings or socket/IPC/file buffers. Use with caution. 29 namespace base { 30 31 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 32 namespace internal { 33 34 // Represents allocator that contains memory for data-like objects (that don't 35 // contain pointers) and therefore doesn't require scanning. 36 template <bool Quarantinable> 37 class BASE_EXPORT NonScannableAllocatorImpl final { 38 public: 39 static NonScannableAllocatorImpl& Instance(); 40 41 NonScannableAllocatorImpl(const NonScannableAllocatorImpl&) = delete; 42 NonScannableAllocatorImpl& operator=(const NonScannableAllocatorImpl&) = 43 delete; 44 45 void* Alloc(size_t size); 46 static void Free(void*); 47 48 // Returns PartitionRoot corresponding to the allocator, or nullptr if the 49 // allocator is not enabled. root()50 partition_alloc::ThreadSafePartitionRoot* root() { 51 #if BUILDFLAG(USE_STARSCAN) 52 if (!allocator_.get()) { 53 return nullptr; 54 } 55 return allocator_->root(); 56 #else 57 return nullptr; 58 #endif // BUILDFLAG(USE_STARSCAN) 59 } 60 61 void NotifyPCScanEnabled(); 62 63 private: 64 template <typename> 65 friend class base::NoDestructor; 66 67 NonScannableAllocatorImpl(); 68 ~NonScannableAllocatorImpl(); 69 70 #if BUILDFLAG(USE_STARSCAN) 71 std::unique_ptr<partition_alloc::PartitionAllocator, 72 partition_alloc::internal::PCScanMetadataDeleter> 73 allocator_; 74 std::atomic_bool pcscan_enabled_{false}; 75 #endif // BUILDFLAG(USE_STARSCAN) 76 }; 77 78 extern template class NonScannableAllocatorImpl<true>; 79 extern template class NonScannableAllocatorImpl<false>; 80 81 using NonScannableAllocator = NonScannableAllocatorImpl<true>; 82 using NonQuarantinableAllocator = NonScannableAllocatorImpl<false>; 83 84 } // namespace internal 85 #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) 86 87 // Allocate/free non-scannable, but still quarantinable memory. 88 BASE_EXPORT void* AllocNonScannable(size_t size); 89 BASE_EXPORT void FreeNonScannable(void* ptr); 90 91 // Allocate/free non-scannable and non-quarantinable memory. These functions 92 // behave as normal, *Scan-unaware allocation functions. This can be useful for 93 // allocations that are guaranteed to be safe by the user, i.e. allocations that 94 // cannot be referenced from outside and cannot contain dangling references 95 // themselves. 96 BASE_EXPORT void* AllocNonQuarantinable(size_t size); 97 BASE_EXPORT void FreeNonQuarantinable(void* ptr); 98 99 // Deleters to be used with std::unique_ptr. 100 struct NonScannableDeleter { operatorNonScannableDeleter101 void operator()(void* ptr) const { FreeNonScannable(ptr); } 102 }; 103 struct NonQuarantinableDeleter { operatorNonQuarantinableDeleter104 void operator()(void* ptr) const { FreeNonQuarantinable(ptr); } 105 }; 106 107 } // namespace base 108 109 #endif // BASE_MEMORY_NONSCANNABLE_MEMORY_H_ 110