Skip to content

Commit

Permalink
[lsan] On Fuchsia, don't use atexit hook for leak checks
Browse files Browse the repository at this point in the history
This is a re-land of https://reviews.llvm.org/D86171 with fix.

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

Differential Revision: https://reviews.llvm.org/D88248
  • Loading branch information
frobtech committed Mar 30, 2022
1 parent 9276074 commit fd7ec90
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 49 deletions.
21 changes: 16 additions & 5 deletions compiler-rt/lib/asan/asan_fuchsia.cpp
Expand Up @@ -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.
Expand Down Expand Up @@ -235,8 +236,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.

Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/asan/asan_internal.h
Expand Up @@ -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) \
Expand Down
47 changes: 30 additions & 17 deletions compiler-rt/lib/asan/asan_posix.cpp
Expand Up @@ -14,22 +14,23 @@
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_POSIX

#include "asan_internal.h"
#include "asan_interceptors.h"
#include "asan_mapping.h"
#include "asan_poisoning.h"
#include "asan_report.h"
#include "asan_stack.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_posix.h"
#include "sanitizer_common/sanitizer_procmaps.h"

#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
# include <pthread.h>
# include <signal.h>
# include <stdlib.h>
# include <sys/resource.h>
# include <sys/time.h>
# include <unistd.h>

# include "asan_interceptors.h"
# include "asan_internal.h"
# include "asan_mapping.h"
# include "asan_poisoning.h"
# include "asan_report.h"
# include "asan_stack.h"
# include "lsan/lsan_common.h"
# include "sanitizer_common/sanitizer_libc.h"
# include "sanitizer_common/sanitizer_posix.h"
# include "sanitizer_common/sanitizer_procmaps.h"

namespace __asan {

Expand Down Expand Up @@ -131,7 +132,7 @@ void AsanTSDSet(void *tsd) {
}

void PlatformTSDDtor(void *tsd) {
AsanThreadContext *context = (AsanThreadContext*)tsd;
AsanThreadContext *context = (AsanThreadContext *)tsd;
if (context->destructor_iterations > 1) {
context->destructor_iterations--;
CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
Expand All @@ -140,6 +141,18 @@ void PlatformTSDDtor(void *tsd) {
AsanThread::TSDDtor(tsd);
}
#endif

void InstallAtExitCheckLeaks() {
if (CAN_SANITIZE_LEAKS) {
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
if (flags()->halt_on_error)
Atexit(__lsan::DoLeakCheck);
else
Atexit(__lsan::DoRecoverableLeakCheckVoid);
}
}
}

} // namespace __asan

#endif // SANITIZER_POSIX
7 changes: 1 addition & 6 deletions compiler-rt/lib/asan/asan_rtl.cpp
Expand Up @@ -477,12 +477,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
Expand Down
38 changes: 20 additions & 18 deletions compiler-rt/lib/asan/asan_win.cpp
@@ -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.
Expand All @@ -13,21 +14,20 @@

#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <stdlib.h>

#include "asan_interceptors.h"
#include "asan_internal.h"
#include "asan_mapping.h"
#include "asan_report.h"
#include "asan_stack.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_mutex.h"
#include "sanitizer_common/sanitizer_win.h"
#include "sanitizer_common/sanitizer_win_defs.h"
# define WIN32_LEAN_AND_MEAN
# include <stdlib.h>
# include <windows.h>

# include "asan_interceptors.h"
# include "asan_internal.h"
# include "asan_mapping.h"
# include "asan_report.h"
# include "asan_stack.h"
# include "asan_thread.h"
# include "sanitizer_common/sanitizer_libc.h"
# include "sanitizer_common/sanitizer_mutex.h"
# include "sanitizer_common/sanitizer_win.h"
# include "sanitizer_common/sanitizer_win_defs.h"

using namespace __asan;

Expand All @@ -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;

Expand Down Expand Up @@ -187,6 +187,8 @@ void InitializePlatformInterceptors() {
}
}

void InstallAtExitCheckLeaks() {}

void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
UNIMPLEMENTED();
}
Expand Down
4 changes: 1 addition & 3 deletions compiler-rt/lib/lsan/lsan.cpp
Expand Up @@ -100,9 +100,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);

Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/lsan/lsan.h
Expand Up @@ -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 { \
Expand Down
9 changes: 9 additions & 0 deletions compiler-rt/lib/lsan/lsan_common_fuchsia.cpp
Expand Up @@ -52,7 +52,16 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {}
// behavior and causes rare race conditions.
void HandleLeaks() {}

// This is defined differently in asan_fuchsia.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;
}

Expand Down
7 changes: 7 additions & 0 deletions compiler-rt/lib/lsan/lsan_fuchsia.cpp
Expand Up @@ -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>.
Expand Down
5 changes: 5 additions & 0 deletions compiler-rt/lib/lsan/lsan_posix.cpp
Expand Up @@ -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

0 comments on commit fd7ec90

Please sign in to comment.