nonscannable_memory.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Copyright (c) 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/memory/nonscannable_memory.h"
  5. #include <stdlib.h>
  6. #include "base/allocator/buildflags.h"
  7. #include "base/feature_list.h"
  8. #include "base/no_destructor.h"
  9. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  10. #include "base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h"
  11. #include "base/allocator/partition_alloc_features.h"
  12. #include "base/allocator/partition_allocator/starscan/pcscan.h"
  13. #endif
  14. namespace base {
  15. namespace internal {
  16. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  17. template <bool Quarantinable>
  18. NonScannableAllocatorImpl<Quarantinable>::NonScannableAllocatorImpl() = default;
  19. template <bool Quarantinable>
  20. NonScannableAllocatorImpl<Quarantinable>::~NonScannableAllocatorImpl() =
  21. default;
  22. template <bool Quarantinable>
  23. NonScannableAllocatorImpl<Quarantinable>&
  24. NonScannableAllocatorImpl<Quarantinable>::Instance() {
  25. static base::NoDestructor<NonScannableAllocatorImpl> instance;
  26. return *instance;
  27. }
  28. template <bool Quarantinable>
  29. void* NonScannableAllocatorImpl<Quarantinable>::Alloc(size_t size) {
  30. // TODO(bikineev): Change to LIKELY once PCScan is enabled by default.
  31. if (UNLIKELY(pcscan_enabled_.load(std::memory_order_acquire))) {
  32. PA_DCHECK(allocator_.get());
  33. return allocator_->root()->AllocWithFlagsNoHooks(
  34. 0, size, partition_alloc::PartitionPageSize());
  35. }
  36. // Otherwise, dispatch to default partition.
  37. return PartitionAllocMalloc::Allocator()->AllocWithFlagsNoHooks(
  38. 0, size, partition_alloc::PartitionPageSize());
  39. }
  40. template <bool Quarantinable>
  41. void NonScannableAllocatorImpl<Quarantinable>::Free(void* ptr) {
  42. partition_alloc::ThreadSafePartitionRoot::FreeNoHooks(ptr);
  43. }
  44. template <bool Quarantinable>
  45. void NonScannableAllocatorImpl<Quarantinable>::NotifyPCScanEnabled() {
  46. allocator_.reset(partition_alloc::internal::MakePCScanMetadata<
  47. partition_alloc::PartitionAllocator>());
  48. allocator_->init({
  49. partition_alloc::PartitionOptions::AlignedAlloc::kDisallowed,
  50. partition_alloc::PartitionOptions::ThreadCache::kDisabled,
  51. Quarantinable
  52. ? partition_alloc::PartitionOptions::Quarantine::kAllowed
  53. : partition_alloc::PartitionOptions::Quarantine::kDisallowed,
  54. partition_alloc::PartitionOptions::Cookie::kAllowed,
  55. partition_alloc::PartitionOptions::BackupRefPtr::kDisabled,
  56. partition_alloc::PartitionOptions::BackupRefPtrZapping::kDisabled,
  57. partition_alloc::PartitionOptions::UseConfigurablePool::kNo,
  58. });
  59. if (Quarantinable)
  60. partition_alloc::internal::PCScan::RegisterNonScannableRoot(
  61. allocator_->root());
  62. pcscan_enabled_.store(true, std::memory_order_release);
  63. }
  64. template class NonScannableAllocatorImpl<true>;
  65. template class NonScannableAllocatorImpl<false>;
  66. #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  67. } // namespace internal
  68. void* AllocNonScannable(size_t size) {
  69. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  70. return internal::NonScannableAllocatorImpl</*Quarantinable=*/true>::Instance()
  71. .Alloc(size);
  72. #else
  73. return ::malloc(size);
  74. #endif
  75. }
  76. void FreeNonScannable(void* ptr) {
  77. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  78. internal::NonScannableAllocatorImpl</*Quarantinable=*/true>::Free(ptr);
  79. #else
  80. return ::free(ptr);
  81. #endif
  82. }
  83. void* AllocNonQuarantinable(size_t size) {
  84. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  85. return internal::NonScannableAllocatorImpl<
  86. /*Quarantinable=*/false>::Instance()
  87. .Alloc(size);
  88. #else
  89. return ::malloc(size);
  90. #endif
  91. }
  92. void FreeNonQuarantinable(void* ptr) {
  93. #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
  94. internal::NonScannableAllocatorImpl</*Quarantinable=*/false>::Free(ptr);
  95. #else
  96. return ::free(ptr);
  97. #endif
  98. }
  99. } // namespace base