1 // Copyright 2022 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_RAW_PTR_ASAN_SERVICE_H_ 6 #define BASE_MEMORY_RAW_PTR_ASAN_SERVICE_H_ 7 8 #include "partition_alloc/partition_alloc_buildflags.h" 9 10 #if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) 11 #include <cstddef> 12 #include <cstdint> 13 14 #include "base/base_export.h" 15 #include "base/compiler_specific.h" 16 #include "base/types/strong_alias.h" 17 18 namespace base { 19 20 using EnableDereferenceCheck = 21 base::StrongAlias<class EnableDereferenceCheckTag, bool>; 22 using EnableExtractionCheck = 23 base::StrongAlias<class EnableExtractionCheckTag, bool>; 24 using EnableInstantiationCheck = 25 base::StrongAlias<class EnableInstantiationCheckTag, bool>; 26 27 class BASE_EXPORT RawPtrAsanService { 28 public: 29 enum class ReportType { 30 kDereference, 31 kExtraction, 32 kInstantiation, 33 }; 34 35 struct PendingReport { 36 ReportType type = ReportType::kDereference; 37 uintptr_t allocation_base = 0; 38 size_t allocation_size = 0; 39 }; 40 41 void Configure(EnableDereferenceCheck, 42 EnableExtractionCheck, 43 EnableInstantiationCheck); 44 45 bool IsSupportedAllocation(void*) const; 46 IsEnabled()47 bool IsEnabled() const { return mode_ == Mode::kEnabled; } 48 49 ALWAYS_INLINE NO_SANITIZE( is_dereference_check_enabled()50 "address") bool is_dereference_check_enabled() const { 51 return is_dereference_check_enabled_; 52 } 53 54 ALWAYS_INLINE NO_SANITIZE( is_extraction_check_enabled()55 "address") bool is_extraction_check_enabled() const { 56 return is_extraction_check_enabled_; 57 } 58 59 ALWAYS_INLINE NO_SANITIZE( is_instantiation_check_enabled()60 "address") bool is_instantiation_check_enabled() const { 61 return is_instantiation_check_enabled_; 62 } 63 GetInstance()64 ALWAYS_INLINE NO_SANITIZE("address") static RawPtrAsanService& GetInstance() { 65 return instance_; 66 } 67 68 void WarnOnDanglingExtraction(const volatile void* ptr) const; 69 void CrashOnDanglingInstantiation(const volatile void* ptr) const; 70 71 static void SetPendingReport(ReportType type, const volatile void* ptr); 72 73 private: 74 enum class Mode { 75 kUninitialized, 76 kDisabled, 77 kEnabled, 78 }; 79 80 uint8_t* GetShadow(void* ptr) const; 81 82 static void MallocHook(const volatile void*, size_t); FreeHook(const volatile void *)83 static void FreeHook(const volatile void*) {} 84 static void ErrorReportCallback(const char* report, 85 bool* should_exit_cleanly); 86 87 Mode mode_ = Mode::kUninitialized; 88 bool is_dereference_check_enabled_ = false; 89 bool is_extraction_check_enabled_ = false; 90 bool is_instantiation_check_enabled_ = false; 91 92 size_t shadow_offset_ = 0; 93 94 static RawPtrAsanService instance_; // Not a static local variable because 95 // `GetInstance()` is used in hot paths. 96 }; 97 98 } // namespace base 99 100 #endif // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) 101 #endif // BASE_MEMORY_RAW_PTR_ASAN_SERVICE_H_ 102