127 lines
4.1 KiB
C++
127 lines
4.1 KiB
C++
// 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 "base/memory/nonscannable_memory.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
|
#include "base/feature_list.h"
|
|
#include "base/no_destructor.h"
|
|
|
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
#include "base/allocator/partition_alloc_features.h"
|
|
#include "base/allocator/partition_allocator/shim/allocator_shim_default_dispatch_to_partition_alloc.h"
|
|
|
|
#if BUILDFLAG(USE_STARSCAN)
|
|
#include "base/allocator/partition_allocator/starscan/metadata_allocator.h"
|
|
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
|
#endif
|
|
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
|
|
namespace base {
|
|
namespace 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 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 (UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) {
|
|
PA_DCHECK(allocator_.get());
|
|
return allocator_->root()->AllocWithFlagsNoHooks(
|
|
0, size, partition_alloc::PartitionPageSize());
|
|
}
|
|
#endif // BUILDFLAG(USE_STARSCAN)
|
|
// Otherwise, dispatch to default partition.
|
|
return allocator_shim::internal::PartitionAllocMalloc::Allocator()
|
|
->AllocWithFlagsNoHooks(0, size, partition_alloc::PartitionPageSize());
|
|
}
|
|
|
|
template <bool Quarantinable>
|
|
void NonScannableAllocatorImpl<Quarantinable>::Free(void* ptr) {
|
|
partition_alloc::ThreadSafePartitionRoot::FreeNoHooks(ptr);
|
|
}
|
|
|
|
template <bool Quarantinable>
|
|
void NonScannableAllocatorImpl<Quarantinable>::NotifyPCScanEnabled() {
|
|
#if BUILDFLAG(USE_STARSCAN)
|
|
allocator_.reset(partition_alloc::internal::MakePCScanMetadata<
|
|
partition_alloc::PartitionAllocator>());
|
|
allocator_->init({
|
|
partition_alloc::PartitionOptions::AlignedAlloc::kDisallowed,
|
|
partition_alloc::PartitionOptions::ThreadCache::kDisabled,
|
|
Quarantinable
|
|
? partition_alloc::PartitionOptions::Quarantine::kAllowed
|
|
: partition_alloc::PartitionOptions::Quarantine::kDisallowed,
|
|
partition_alloc::PartitionOptions::Cookie::kAllowed,
|
|
partition_alloc::PartitionOptions::BackupRefPtr::kDisabled,
|
|
partition_alloc::PartitionOptions::BackupRefPtrZapping::kDisabled,
|
|
partition_alloc::PartitionOptions::UseConfigurablePool::kNo,
|
|
});
|
|
if (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 internal
|
|
|
|
void* AllocNonScannable(size_t size) {
|
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
return internal::NonScannableAllocatorImpl</*Quarantinable=*/true>::Instance()
|
|
.Alloc(size);
|
|
#else
|
|
return ::malloc(size);
|
|
#endif
|
|
}
|
|
|
|
void FreeNonScannable(void* ptr) {
|
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
internal::NonScannableAllocatorImpl</*Quarantinable=*/true>::Free(ptr);
|
|
#else
|
|
return ::free(ptr);
|
|
#endif
|
|
}
|
|
|
|
void* AllocNonQuarantinable(size_t size) {
|
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
return internal::NonScannableAllocatorImpl<
|
|
/*Quarantinable=*/false>::Instance()
|
|
.Alloc(size);
|
|
#else
|
|
return ::malloc(size);
|
|
#endif
|
|
}
|
|
|
|
void FreeNonQuarantinable(void* ptr) {
|
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
internal::NonScannableAllocatorImpl</*Quarantinable=*/false>::Free(ptr);
|
|
#else
|
|
return ::free(ptr);
|
|
#endif
|
|
}
|
|
|
|
} // namespace base
|