[lsan] On Fuchsia, don't use atexit hook for leak checks

Fuchsia's system libraries are instrumented and use the lsan
allocator for internal purposes.  So leak checking needs to run
after all atexit hooks and after the system libraries' internal
exit-time hooks.  The <zircon/sanitizer.h> hook API calls the
__sanitizer_process_exit_hook function at exactly the right time.

Reviewed By: vitalybuka, phosek

Differential Revision: https://reviews.llvm.org/D86171
This commit is contained in:
Roland McGrath 2020-09-22 18:02:56 -07:00
parent 5281ba1994
commit 0caad9fe44
10 changed files with 65 additions and 21 deletions

View File

@ -14,16 +14,17 @@
#include "sanitizer_common/sanitizer_fuchsia.h"
#if SANITIZER_FUCHSIA
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_stack.h"
#include "asan_thread.h"
#include <limits.h>
#include <zircon/sanitizer.h>
#include <zircon/syscalls.h>
#include <zircon/threads.h>
#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_stack.h"
#include "asan_thread.h"
#include "lsan/lsan_common.h"
namespace __asan {
// The system already set up the shadow memory for us.
@ -31,7 +32,8 @@ namespace __asan {
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
// Just do some additional sanity checks here.
void InitializeShadowMemory() {
if (Verbosity()) PrintAddressSpaceLayout();
if (Verbosity())
PrintAddressSpaceLayout();
// Make sure SHADOW_OFFSET doesn't use __asan_shadow_memory_dynamic_address.
__asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
@ -148,7 +150,8 @@ static void *BeforeThreadCreateHook(uptr user_id, bool detached,
uptr stack_size) {
EnsureMainThreadIDIsCorrect();
// Strict init-order checking is thread-hostile.
if (flags()->strict_init_order) StopInitOrderChecking();
if (flags()->strict_init_order)
StopInitOrderChecking();
GET_STACK_TRACE_THREAD;
u32 parent_tid = GetCurrentTidOrInvalid();
@ -202,8 +205,18 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) {
__sanitizer_fill_shadow(p, size, 0, 0);
}
// On Fuchsia, leak detection is done by a special hook after atexit hooks.
// So this doesn't install any atexit hook like on other platforms.
void InstallAtExitCheckLeaks() {}
} // namespace __asan
namespace __lsan {
bool UseExitcodeOnLeak() { return __asan::flags()->halt_on_error; }
} // namespace __lsan
// These are declared (in extern "C") by <zircon/sanitizer.h>.
// The system runtime will call our definitions directly.

View File

@ -123,6 +123,8 @@ void *AsanDlSymNext(const char *sym);
// `dlopen()` specific initialization inside this function.
bool HandleDlopenInit();
void InstallAtExitCheckLeaks();
// Add convenient macro for interface functions that may be represented as
// weak hooks.
#define ASAN_MALLOC_HOOK(ptr, size) \

View File

@ -140,6 +140,18 @@ void PlatformTSDDtor(void *tsd) {
AsanThread::TSDDtor(tsd);
}
#endif
#if CAN_SANITIZE_LEAKS
void InstallAtExitCheckLeaks() {
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
if (flags()->halt_on_error)
Atexit(__lsan::DoLeakCheck);
else
Atexit(__lsan::DoRecoverableLeakCheckVoid);
}
}
#endif
} // namespace __asan
#endif // SANITIZER_POSIX

View File

@ -500,12 +500,7 @@ static void AsanInitInternal() {
if (CAN_SANITIZE_LEAKS) {
__lsan::InitCommonLsan();
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
if (flags()->halt_on_error)
Atexit(__lsan::DoLeakCheck);
else
Atexit(__lsan::DoRecoverableLeakCheckVoid);
}
InstallAtExitCheckLeaks();
}
#if CAN_SANITIZE_UB

View File

@ -1,4 +1,5 @@
//===-- asan_win.cpp ------------------------------------------------------===//
//===-- asan_win.cpp
//------------------------------------------------------===//>
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -14,9 +15,8 @@
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <windows.h>
#include "asan_interceptors.h"
#include "asan_internal.h"
@ -49,8 +49,8 @@ uptr __asan_get_shadow_memory_dynamic_address() {
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
static LPTOP_LEVEL_EXCEPTION_FILTER user_seh_handler;
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) {
extern "C" SANITIZER_INTERFACE_ATTRIBUTE long __asan_unhandled_exception_filter(
EXCEPTION_POINTERS *info) {
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
CONTEXT *context = info->ContextRecord;
@ -187,6 +187,8 @@ void InitializePlatformInterceptors() {
}
}
void InstallAtExitCheckLeaks() {}
void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
UNIMPLEMENTED();
}

View File

@ -103,9 +103,7 @@ extern "C" void __lsan_init() {
InitializeThreadRegistry();
InstallDeadlySignalHandlers(LsanOnDeadlySignal);
InitializeMainThread();
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
Atexit(DoLeakCheck);
InstallAtExitCheckLeaks();
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);

View File

@ -39,6 +39,7 @@ namespace __lsan {
void InitializeInterceptors();
void ReplaceSystemMalloc();
void LsanOnDeadlySignal(int signo, void *siginfo, void *context);
void InstallAtExitCheckLeaks();
#define ENSURE_LSAN_INITED do { \
CHECK(!lsan_init_is_running); \

View File

@ -51,7 +51,16 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {}
// behavior and causes rare race conditions.
void HandleLeaks() {}
// This is defined differently in asan_fuchsiap.cpp and lsan_fuchsia.cpp.
bool UseExitcodeOnLeak();
int ExitHook(int status) {
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
if (UseExitcodeOnLeak())
DoLeakCheck();
else
DoRecoverableLeakCheckVoid();
}
return status == 0 && HasReportedLeaks() ? common_flags()->exitcode : status;
}

View File

@ -76,6 +76,13 @@ void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {
caches);
}
// On Fuchsia, leak detection is done by a special hook after atexit hooks.
// So this doesn't install any atexit hook like on other platforms.
void InstallAtExitCheckLeaks() {}
// ASan defines this to check its `halt_on_error` flag.
bool UseExitcodeOnLeak() { return true; }
} // namespace __lsan
// These are declared (in extern "C") by <zircon/sanitizer.h>.

View File

@ -91,6 +91,11 @@ void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {
nullptr);
}
void InstallAtExitCheckLeaks() {
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
Atexit(DoLeakCheck);
}
} // namespace __lsan
#endif // SANITIZER_POSIX