• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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