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_DEBUG_ASAN_SERVICE_H_ 6 #define BASE_DEBUG_ASAN_SERVICE_H_ 7 8 #if defined(ADDRESS_SANITIZER) 9 10 #include <string> 11 #include <vector> 12 13 #include "base/base_export.h" 14 #include "base/no_destructor.h" 15 #include "base/synchronization/lock.h" 16 #include "base/thread_annotations.h" 17 18 namespace base { 19 namespace debug { 20 21 // This implements an abstraction layer for the parts of the AddressSanitizer 22 // API used to receive callbacks during crash handling. This is used to add 23 // application-specific information into the AddressSanitizer error messages 24 // to assist with debugging, and to filter known false-positive crashes during 25 // fuzz testing. 26 class BASE_EXPORT AsanService { 27 public: 28 // We can't use a base::Callback type here as we need execution of these 29 // callbacks to be as simple as possible. 30 // 31 // `reason` points to a string containing the AddressSanitizer error report. 32 // `should_exit_cleanly` should be set to true only if the callback determines 33 // that this crash is known to be safe - this will override the normal ASan 34 // behaviour and instead exit cleanly. If your callback is modifying this 35 // parameter, it should log a message explaining why this error is known to 36 // be safe. 37 using ErrorCallback = void (*)(const char* reason, bool* should_exit_cleanly); 38 39 static AsanService* GetInstance(); 40 41 // Registers the global AddressSanitizer error report callback. Any callbacks 42 // registered by calls to AddErrorCallback will become active after this is 43 // complete. Safe to call from any thread, and safe to call multiple times. 44 void Initialize() LOCKS_EXCLUDED(lock_); 45 46 // Writes a message to the same log as AddressSanitizer. This should be used 47 // for logging inside callbacks. Safe to call from any thread. 48 void Log(const char* format, ...); 49 50 // Adds an error callback that will be called on the faulting thread when 51 // Address Sanitizer detects an error. All registered callbacks are called 52 // for every error. Safe to call from any thread, and the callback registered 53 // must also be safe to call from any thread. 54 void AddErrorCallback(ErrorCallback error_callback) LOCKS_EXCLUDED(lock_); 55 56 private: 57 friend class AsanServiceTest; 58 friend class base::NoDestructor<AsanService>; 59 60 AsanService(); 61 ~AsanService() = delete; 62 63 void RunErrorCallbacks(const char* reason) LOCKS_EXCLUDED(lock_); 64 65 // This is the error report entrypoint function that is registered with 66 // AddressSanitizer. 67 static void ErrorReportCallback(const char* reason); 68 69 // Guards all of the internal state, so that we can safely handle concurrent 70 // errors on multiple threads. 71 Lock lock_; 72 73 // Ensure that we don't try and register callbacks before calling Initialize. 74 bool is_initialized_ GUARDED_BY(lock_) = false; 75 76 // The list of currently registered error callbacks. 77 std::vector<ErrorCallback> error_callbacks_ GUARDED_BY(lock_); 78 }; 79 80 } // namespace debug 81 } // namespace base 82 83 #endif // defined(ADDRESS_SANITIZER) 84 #endif // BASE_DEBUG_ASAN_SERVICE_H_ 85