blob: 7aa8c867522b513a63c9d2c9b647a50266fe6de3 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "partition_alloc/shim/nonscannable_allocator.h"
#include "partition_alloc/partition_root.h"
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
#include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h"
#if BUILDFLAG(USE_STARSCAN)
#include "partition_alloc/starscan/metadata_allocator.h"
#include "partition_alloc/starscan/pcscan.h"
#endif
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
namespace allocator_shim::internal {
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
template <bool quarantinable>
NonScannableAllocatorImpl<quarantinable>::NonScannableAllocatorImpl() = default;
template <bool quarantinable>
NonScannableAllocatorImpl<quarantinable>::~NonScannableAllocatorImpl() =
default;
template <bool quarantinable>
NonScannableAllocatorImpl<quarantinable>&
NonScannableAllocatorImpl<quarantinable>::Instance() {
static partition_alloc::internal::base::NoDestructor<
NonScannableAllocatorImpl>
instance;
return *instance;
}
template <bool quarantinable>
void* NonScannableAllocatorImpl<quarantinable>::Alloc(size_t size) {
#if BUILDFLAG(USE_STARSCAN)
// TODO(bikineev): Change to LIKELY once PCScan is enabled by default.
if (PA_UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) {
PA_DCHECK(allocator_.get());
return allocator_->root()
->AllocInline<partition_alloc::AllocFlags::kNoHooks>(size);
}
#endif // BUILDFLAG(USE_STARSCAN)
// Otherwise, dispatch to default partition.
return allocator_shim::internal::PartitionAllocMalloc::Allocator()
->AllocInline<partition_alloc::AllocFlags::kNoHooks>(size);
}
template <bool quarantinable>
void NonScannableAllocatorImpl<quarantinable>::Free(void* ptr) {
#if BUILDFLAG(USE_STARSCAN)
if (PA_UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) {
allocator_->root()->FreeInline<partition_alloc::FreeFlags::kNoHooks>(ptr);
return;
}
#endif // BUILDFLAG(USE_STARSCAN)
partition_alloc::PartitionRoot::FreeInlineInUnknownRoot<
partition_alloc::FreeFlags::kNoHooks>(ptr);
}
template <bool quarantinable>
void NonScannableAllocatorImpl<quarantinable>::NotifyPCScanEnabled() {
#if BUILDFLAG(USE_STARSCAN)
partition_alloc::PartitionOptions opts;
opts.star_scan_quarantine =
quarantinable ? partition_alloc::PartitionOptions::kAllowed
: partition_alloc::PartitionOptions::kDisallowed;
opts.backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled;
allocator_.reset(partition_alloc::internal::MakePCScanMetadata<
partition_alloc::PartitionAllocator>(opts));
if constexpr (quarantinable) {
partition_alloc::internal::PCScan::RegisterNonScannableRoot(
allocator_->root());
}
pcscan_enabled_.store(true, std::memory_order_release);
#endif // BUILDFLAG(USE_STARSCAN)
}
template class NonScannableAllocatorImpl<true>;
template class NonScannableAllocatorImpl<false>;
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
} // namespace allocator_shim::internal