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 PARTITION_ALLOC_SHIM_NONSCANNABLE_ALLOCATOR_H_
6 #define PARTITION_ALLOC_SHIM_NONSCANNABLE_ALLOCATOR_H_
7 
8 #include <atomic>
9 #include <cstddef>
10 #include <memory>
11 
12 #include "partition_alloc/partition_alloc_base/component_export.h"
13 #include "partition_alloc/partition_alloc_base/export_template.h"
14 #include "partition_alloc/partition_alloc_base/no_destructor.h"
15 #include "partition_alloc/partition_alloc_buildflags.h"
16 
17 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
18 #include "partition_alloc/partition_alloc.h"
19 
20 #if BUILDFLAG(USE_STARSCAN)
21 #include "partition_alloc/internal_allocator_forward.h"
22 #endif
23 #endif  // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
24 
25 namespace allocator_shim {
26 
27 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
28 namespace internal {
29 
30 // Represents allocator that contains memory for data-like objects (that don't
31 // contain pointers/references) and therefore doesn't require scanning by
32 // PCScan. An example would be strings or socket/IPC/file buffers. Use with
33 // caution.
34 template <bool quarantinable>
35 class NonScannableAllocatorImpl final {
36  public:
37   static NonScannableAllocatorImpl& Instance();
38 
39   NonScannableAllocatorImpl(const NonScannableAllocatorImpl&) = delete;
40   NonScannableAllocatorImpl& operator=(const NonScannableAllocatorImpl&) =
41       delete;
42 
43   void* Alloc(size_t size);
44   void Free(void*);
45 
46   // Returns PartitionRoot corresponding to the allocator, or nullptr if the
47   // allocator is not enabled.
root()48   partition_alloc::PartitionRoot* root() {
49 #if BUILDFLAG(USE_STARSCAN)
50     if (!allocator_.get()) {
51       return nullptr;
52     }
53     return allocator_->root();
54 #else
55     return nullptr;
56 #endif  // BUILDFLAG(USE_STARSCAN)
57   }
58 
59   void NotifyPCScanEnabled();
60 
61  private:
62   template <typename>
63   friend class partition_alloc::internal::base::NoDestructor;
64 
65   NonScannableAllocatorImpl();
66   ~NonScannableAllocatorImpl();
67 
68 #if BUILDFLAG(USE_STARSCAN)
69   std::unique_ptr<partition_alloc::PartitionAllocator,
70                   partition_alloc::internal::InternalPartitionDeleter>
71       allocator_;
72   std::atomic_bool pcscan_enabled_{false};
73 #endif  // BUILDFLAG(USE_STARSCAN)
74 };
75 
76 extern template class PA_EXPORT_TEMPLATE_DECLARE(
77     PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)) NonScannableAllocatorImpl<true>;
78 extern template class PA_EXPORT_TEMPLATE_DECLARE(
79     PA_COMPONENT_EXPORT(ALLOCATOR_SHIM)) NonScannableAllocatorImpl<false>;
80 
81 }  // namespace internal
82 
83 using NonScannableAllocator = internal::NonScannableAllocatorImpl<true>;
84 using NonQuarantinableAllocator = internal::NonScannableAllocatorImpl<false>;
85 
86 #endif  // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
87 
88 }  // namespace allocator_shim
89 
90 #endif  // PARTITION_ALLOC_SHIM_NONSCANNABLE_ALLOCATOR_H_
91