forked from OSchip/llvm-project
[GWP-ASan] Minor refactor of optional components.
In preparation for the inbuilt options parser, this is a minor refactor of optional components including: - Putting certain optional elements in the right header files, according to their function and their dependencies. - Cleaning up some old and mostly-dead code. - Moving some functions into anonymous namespaces to prevent symbol export. Reviewed By: cryptoad, eugenis Differential Revision: https://reviews.llvm.org/D94117
This commit is contained in:
parent
64e9e9aeee
commit
a8520f6970
|
@ -9,21 +9,45 @@
|
|||
#ifndef GWP_ASAN_OPTIONAL_BACKTRACE_H_
|
||||
#define GWP_ASAN_OPTIONAL_BACKTRACE_H_
|
||||
|
||||
#include "gwp_asan/optional/segv_handler.h"
|
||||
#include "gwp_asan/optional/printf.h"
|
||||
#include "gwp_asan/options.h"
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace options {
|
||||
// Functions to get the platform-specific and implementation-specific backtrace
|
||||
// and backtrace printing functions when RTGwpAsanBacktraceLibc or
|
||||
// RTGwpAsanBacktraceSanitizerCommon are linked. Use these functions to get the
|
||||
// backtrace function for populating the Options::Backtrace and
|
||||
// Options::PrintBacktrace when initialising the GuardedPoolAllocator. Please
|
||||
// note any thread-safety descriptions for the implementation of these functions
|
||||
// that you use.
|
||||
Backtrace_t getBacktraceFunction();
|
||||
crash_handler::PrintBacktrace_t getPrintBacktraceFunction();
|
||||
} // namespace options
|
||||
namespace backtrace {
|
||||
// ================================ Description ================================
|
||||
// This function shall take the backtrace provided in `TraceBuffer`, and print
|
||||
// it in a human-readable format using `Print`. Generally, this function shall
|
||||
// resolve raw pointers to section offsets and print them with the following
|
||||
// sanitizer-common format:
|
||||
// " #{frame_number} {pointer} in {function name} ({binary name}+{offset}"
|
||||
// e.g. " #5 0x420459 in _start (/tmp/uaf+0x420459)"
|
||||
// This format allows the backtrace to be symbolized offline successfully using
|
||||
// llvm-symbolizer.
|
||||
// =================================== Notes ===================================
|
||||
// This function may directly or indirectly call malloc(), as the
|
||||
// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
|
||||
// recursion. Any allocation made inside this function will be served by the
|
||||
// supporting allocator, and will not have GWP-ASan protections.
|
||||
typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength,
|
||||
Printf_t Print);
|
||||
|
||||
// Returns a function pointer to a backtrace function that's suitable for
|
||||
// unwinding through a signal handler. This is important primarily for frame-
|
||||
// pointer based unwinders, DWARF or other unwinders can simply provide the
|
||||
// normal backtrace function as the implementation here. On POSIX, SignalContext
|
||||
// should be the `ucontext_t` from the signal handler.
|
||||
typedef size_t (*SegvBacktrace_t)(uintptr_t *TraceBuffer, size_t Size,
|
||||
void *SignalContext);
|
||||
|
||||
// Returns platform-specific provided implementations of Backtrace_t for use
|
||||
// inside the GWP-ASan core allocator.
|
||||
options::Backtrace_t getBacktraceFunction();
|
||||
|
||||
// Returns platform-specific provided implementations of PrintBacktrace_t and
|
||||
// SegvBacktrace_t for use in the optional SEGV handler.
|
||||
PrintBacktrace_t getPrintBacktraceFunction();
|
||||
SegvBacktrace_t getSegvBacktraceFunction();
|
||||
} // namespace backtrace
|
||||
} // namespace gwp_asan
|
||||
|
||||
#endif // GWP_ASAN_OPTIONAL_BACKTRACE_H_
|
||||
|
|
|
@ -11,12 +11,11 @@
|
|||
// GWP-ASan on Fuchsia doesn't currently support backtraces.
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace options {
|
||||
Backtrace_t getBacktraceFunction() { return nullptr; }
|
||||
crash_handler::PrintBacktrace_t getPrintBacktraceFunction() { return nullptr; }
|
||||
} // namespace options
|
||||
namespace backtrace {
|
||||
|
||||
namespace crash_handler {
|
||||
options::Backtrace_t getBacktraceFunction() { return nullptr; }
|
||||
PrintBacktrace_t getPrintBacktraceFunction() { return nullptr; }
|
||||
SegvBacktrace_t getSegvBacktraceFunction() { return nullptr; }
|
||||
} // namespace crash_handler
|
||||
|
||||
} // namespace backtrace
|
||||
} // namespace gwp_asan
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gwp_asan/definitions.h"
|
||||
#include "gwp_asan/optional/backtrace.h"
|
||||
#include "gwp_asan/optional/printf.h"
|
||||
#include "gwp_asan/options.h"
|
||||
|
||||
namespace {
|
||||
|
@ -32,7 +34,7 @@ GWP_ASAN_ALWAYS_INLINE size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size,
|
|||
}
|
||||
|
||||
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
|
||||
gwp_asan::crash_handler::Printf_t Printf) {
|
||||
gwp_asan::Printf_t Printf) {
|
||||
if (TraceLength == 0) {
|
||||
Printf(" <not found (does your allocator support backtracing?)>\n\n");
|
||||
return;
|
||||
|
@ -55,14 +57,11 @@ static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
|
|||
} // anonymous namespace
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace options {
|
||||
Backtrace_t getBacktraceFunction() { return Backtrace; }
|
||||
crash_handler::PrintBacktrace_t getPrintBacktraceFunction() {
|
||||
return PrintBacktrace;
|
||||
}
|
||||
} // namespace options
|
||||
namespace backtrace {
|
||||
|
||||
namespace crash_handler {
|
||||
options::Backtrace_t getBacktraceFunction() { return Backtrace; }
|
||||
PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
|
||||
SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
|
||||
} // namespace crash_handler
|
||||
|
||||
} // namespace backtrace
|
||||
} // namespace gwp_asan
|
||||
|
|
|
@ -62,7 +62,7 @@ size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size, void *Context) {
|
|||
}
|
||||
|
||||
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
|
||||
gwp_asan::crash_handler::Printf_t Printf) {
|
||||
gwp_asan::Printf_t Printf) {
|
||||
__sanitizer::StackTrace StackTrace;
|
||||
StackTrace.trace = reinterpret_cast<__sanitizer::uptr *>(Trace);
|
||||
StackTrace.size = TraceLength;
|
||||
|
@ -77,25 +77,23 @@ static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
|
|||
} // anonymous namespace
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace options {
|
||||
namespace backtrace {
|
||||
|
||||
// This function is thread-compatible. It must be synchronised in respect to any
|
||||
// other calls to getBacktraceFunction(), calls to getPrintBacktraceFunction(),
|
||||
// and calls to either of the functions that they return. Furthermore, this may
|
||||
// require synchronisation with any calls to sanitizer_common that use flags.
|
||||
// Generally, this function will be called during the initialisation of the
|
||||
// allocator, which is done in a thread-compatible manner.
|
||||
Backtrace_t getBacktraceFunction() {
|
||||
options::Backtrace_t getBacktraceFunction() {
|
||||
// The unwinder requires the default flags to be set.
|
||||
__sanitizer::SetCommonFlagsDefaults();
|
||||
__sanitizer::InitializeCommonFlags();
|
||||
return Backtrace;
|
||||
}
|
||||
crash_handler::PrintBacktrace_t getPrintBacktraceFunction() {
|
||||
return PrintBacktrace;
|
||||
}
|
||||
} // namespace options
|
||||
|
||||
namespace crash_handler {
|
||||
PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
|
||||
SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
|
||||
} // namespace crash_handler
|
||||
|
||||
} // namespace backtrace
|
||||
} // namespace gwp_asan
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
//===-- printf.h ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef GWP_ASAN_OPTIONAL_PRINTF_H_
|
||||
#define GWP_ASAN_OPTIONAL_PRINTF_H_
|
||||
|
||||
namespace gwp_asan {
|
||||
|
||||
// ================================ Requirements ===============================
|
||||
// This function is required to be provided by the supporting allocator iff the
|
||||
// allocator wants to use any of the optional components.
|
||||
// ================================ Description ================================
|
||||
// This function shall produce output according to a strict subset of the C
|
||||
// standard library's printf() family. This function must support printing the
|
||||
// following formats:
|
||||
// 1. integers: "%([0-9]*)?(z|ll)?{d,u,x,X}"
|
||||
// 2. pointers: "%p"
|
||||
// 3. strings: "%[-]([0-9]*)?(\\.\\*)?s"
|
||||
// 4. chars: "%c"
|
||||
// This function must be implemented in a signal-safe manner, and thus must not
|
||||
// malloc().
|
||||
// =================================== Notes ===================================
|
||||
// This function has a slightly different signature than the C standard
|
||||
// library's printf(). Notably, it returns 'void' rather than 'int'.
|
||||
typedef void (*Printf_t)(const char *Format, ...);
|
||||
|
||||
} // namespace gwp_asan
|
||||
#endif // GWP_ASAN_OPTIONAL_PRINTF_H_
|
|
@ -10,64 +10,11 @@
|
|||
#define GWP_ASAN_OPTIONAL_SEGV_HANDLER_H_
|
||||
|
||||
#include "gwp_asan/guarded_pool_allocator.h"
|
||||
#include "gwp_asan/options.h"
|
||||
#include "gwp_asan/optional/backtrace.h"
|
||||
#include "gwp_asan/optional/printf.h"
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace crash_handler {
|
||||
// ================================ Requirements ===============================
|
||||
// This function must be provided by the supporting allocator only when this
|
||||
// provided crash handler is used to dump the generic report.
|
||||
// sanitizer::Printf() function can be simply used here.
|
||||
// ================================ Description ================================
|
||||
// This function shall produce output according to a strict subset of the C
|
||||
// standard library's printf() family. This function must support printing the
|
||||
// following formats:
|
||||
// 1. integers: "%([0-9]*)?(z|ll)?{d,u,x,X}"
|
||||
// 2. pointers: "%p"
|
||||
// 3. strings: "%[-]([0-9]*)?(\\.\\*)?s"
|
||||
// 4. chars: "%c"
|
||||
// This function must be implemented in a signal-safe manner, and thus must not
|
||||
// malloc().
|
||||
// =================================== Notes ===================================
|
||||
// This function has a slightly different signature than the C standard
|
||||
// library's printf(). Notably, it returns 'void' rather than 'int'.
|
||||
typedef void (*Printf_t)(const char *Format, ...);
|
||||
|
||||
// ================================ Requirements ===============================
|
||||
// This function is required for the supporting allocator, but one of the three
|
||||
// provided implementations may be used (RTGwpAsanBacktraceLibc,
|
||||
// RTGwpAsanBacktraceSanitizerCommon, or BasicPrintBacktraceFunction).
|
||||
// ================================ Description ================================
|
||||
// This function shall take the backtrace provided in `TraceBuffer`, and print
|
||||
// it in a human-readable format using `Print`. Generally, this function shall
|
||||
// resolve raw pointers to section offsets and print them with the following
|
||||
// sanitizer-common format:
|
||||
// " #{frame_number} {pointer} in {function name} ({binary name}+{offset}"
|
||||
// e.g. " #5 0x420459 in _start (/tmp/uaf+0x420459)"
|
||||
// This format allows the backtrace to be symbolized offline successfully using
|
||||
// llvm-symbolizer.
|
||||
// =================================== Notes ===================================
|
||||
// This function may directly or indirectly call malloc(), as the
|
||||
// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
|
||||
// recursion. Any allocation made inside this function will be served by the
|
||||
// supporting allocator, and will not have GWP-ASan protections.
|
||||
typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength,
|
||||
Printf_t Print);
|
||||
|
||||
// Returns a function pointer to a basic PrintBacktrace implementation. This
|
||||
// implementation simply prints the stack trace in a human readable fashion
|
||||
// without any symbolization.
|
||||
PrintBacktrace_t getBasicPrintBacktraceFunction();
|
||||
|
||||
// Returns a function pointer to a backtrace function that's suitable for
|
||||
// unwinding through a signal handler. This is important primarily for frame-
|
||||
// pointer based unwinders, DWARF or other unwinders can simply provide the
|
||||
// normal backtrace function as the implementation here. On POSIX, SignalContext
|
||||
// should be the `ucontext_t` from the signal handler.
|
||||
typedef size_t (*SegvBacktrace_t)(uintptr_t *TraceBuffer, size_t Size,
|
||||
void *SignalContext);
|
||||
SegvBacktrace_t getSegvBacktraceFunction();
|
||||
|
||||
namespace segv_handler {
|
||||
// Install the SIGSEGV crash handler for printing use-after-free and heap-
|
||||
// buffer-{under|over}flow exceptions if the user asked for it. This is platform
|
||||
// specific as even though POSIX and Windows both support registering handlers
|
||||
|
@ -75,16 +22,12 @@ SegvBacktrace_t getSegvBacktraceFunction();
|
|||
// the address that caused the SIGSEGV exception. GPA->init() must be called
|
||||
// before this function.
|
||||
void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
|
||||
PrintBacktrace_t PrintBacktrace,
|
||||
SegvBacktrace_t SegvBacktrace);
|
||||
gwp_asan::backtrace::PrintBacktrace_t PrintBacktrace,
|
||||
gwp_asan::backtrace::SegvBacktrace_t SegvBacktrace);
|
||||
|
||||
// Uninistall the signal handlers, test-only.
|
||||
void uninstallSignalHandlers();
|
||||
|
||||
void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
|
||||
const gwp_asan::AllocationMetadata *Metadata,
|
||||
SegvBacktrace_t SegvBacktrace, Printf_t Printf,
|
||||
PrintBacktrace_t PrintBacktrace, void *Context);
|
||||
} // namespace crash_handler
|
||||
} // namespace segv_handler
|
||||
} // namespace gwp_asan
|
||||
|
||||
#endif // GWP_ASAN_OPTIONAL_SEGV_HANDLER_H_
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
// GWP-ASan on Fuchsia doesn't currently support signal handlers.
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace crash_handler {
|
||||
namespace segv_handler {
|
||||
void installSignalHandlers(gwp_asan::GuardedPoolAllocator * /* GPA */,
|
||||
Printf_t /* Printf */,
|
||||
PrintBacktrace_t /* PrintBacktrace */,
|
||||
SegvBacktrace_t /* SegvBacktrace */) {}
|
||||
backtrace::PrintBacktrace_t /* PrintBacktrace */,
|
||||
backtrace::SegvBacktrace_t /* SegvBacktrace */) {}
|
||||
|
||||
void uninstallSignalHandlers() {}
|
||||
} // namespace crash_handler
|
||||
} // namespace segv_handler
|
||||
} // namespace gwp_asan
|
||||
|
|
|
@ -12,62 +12,30 @@
|
|||
#include "gwp_asan/optional/segv_handler.h"
|
||||
#include "gwp_asan/options.h"
|
||||
|
||||
// RHEL creates the PRIu64 format macro (for printing uint64_t's) only when this
|
||||
// macro is defined before including <inttypes.h>.
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace {
|
||||
using gwp_asan::AllocationMetadata;
|
||||
using gwp_asan::Error;
|
||||
using gwp_asan::GuardedPoolAllocator;
|
||||
using gwp_asan::crash_handler::PrintBacktrace_t;
|
||||
using gwp_asan::crash_handler::Printf_t;
|
||||
using gwp_asan::crash_handler::SegvBacktrace_t;
|
||||
using gwp_asan::Printf_t;
|
||||
using gwp_asan::backtrace::PrintBacktrace_t;
|
||||
using gwp_asan::backtrace::SegvBacktrace_t;
|
||||
|
||||
struct sigaction PreviousHandler;
|
||||
bool SignalHandlerInstalled;
|
||||
gwp_asan::GuardedPoolAllocator *GPAForSignalHandler;
|
||||
Printf_t PrintfForSignalHandler;
|
||||
PrintBacktrace_t PrintBacktraceForSignalHandler;
|
||||
SegvBacktrace_t BacktraceForSignalHandler;
|
||||
|
||||
static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) {
|
||||
if (GPAForSignalHandler) {
|
||||
GPAForSignalHandler->stop();
|
||||
|
||||
gwp_asan::crash_handler::dumpReport(
|
||||
reinterpret_cast<uintptr_t>(info->si_addr),
|
||||
GPAForSignalHandler->getAllocatorState(),
|
||||
GPAForSignalHandler->getMetadataRegion(), BacktraceForSignalHandler,
|
||||
PrintfForSignalHandler, PrintBacktraceForSignalHandler, ucontext);
|
||||
}
|
||||
|
||||
// Process any previous handlers.
|
||||
if (PreviousHandler.sa_flags & SA_SIGINFO) {
|
||||
PreviousHandler.sa_sigaction(sig, info, ucontext);
|
||||
} else if (PreviousHandler.sa_handler == SIG_DFL) {
|
||||
// If the previous handler was the default handler, cause a core dump.
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
raise(SIGSEGV);
|
||||
} else if (PreviousHandler.sa_handler == SIG_IGN) {
|
||||
// If the previous segv handler was SIGIGN, crash iff we were responsible
|
||||
// for the crash.
|
||||
if (__gwp_asan_error_is_mine(GPAForSignalHandler->getAllocatorState(),
|
||||
reinterpret_cast<uintptr_t>(info->si_addr))) {
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
raise(SIGSEGV);
|
||||
}
|
||||
} else {
|
||||
PreviousHandler.sa_handler(sig);
|
||||
}
|
||||
}
|
||||
namespace {
|
||||
|
||||
struct ScopedEndOfReportDecorator {
|
||||
ScopedEndOfReportDecorator(gwp_asan::crash_handler::Printf_t Printf)
|
||||
: Printf(Printf) {}
|
||||
ScopedEndOfReportDecorator(gwp_asan::Printf_t Printf) : Printf(Printf) {}
|
||||
~ScopedEndOfReportDecorator() { Printf("*** End GWP-ASan report ***\n"); }
|
||||
gwp_asan::crash_handler::Printf_t Printf;
|
||||
gwp_asan::Printf_t Printf;
|
||||
};
|
||||
|
||||
// Prints the provided error and metadata information.
|
||||
|
@ -117,47 +85,6 @@ void printHeader(Error E, uintptr_t AccessPtr,
|
|||
AccessPtr, DescriptionBuffer, ThreadBuffer);
|
||||
}
|
||||
|
||||
void defaultPrintStackTrace(uintptr_t *Trace, size_t TraceLength,
|
||||
gwp_asan::crash_handler::Printf_t Printf) {
|
||||
if (TraceLength == 0)
|
||||
Printf(" <unknown (does your allocator support backtracing?)>\n");
|
||||
|
||||
for (size_t i = 0; i < TraceLength; ++i) {
|
||||
Printf(" #%zu 0x%zx in <unknown>\n", i, Trace[i]);
|
||||
}
|
||||
Printf("\n");
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace crash_handler {
|
||||
PrintBacktrace_t getBasicPrintBacktraceFunction() {
|
||||
return defaultPrintStackTrace;
|
||||
}
|
||||
|
||||
void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
|
||||
PrintBacktrace_t PrintBacktrace,
|
||||
SegvBacktrace_t SegvBacktrace) {
|
||||
GPAForSignalHandler = GPA;
|
||||
PrintfForSignalHandler = Printf;
|
||||
PrintBacktraceForSignalHandler = PrintBacktrace;
|
||||
BacktraceForSignalHandler = SegvBacktrace;
|
||||
|
||||
struct sigaction Action = {};
|
||||
Action.sa_sigaction = sigSegvHandler;
|
||||
Action.sa_flags = SA_SIGINFO;
|
||||
sigaction(SIGSEGV, &Action, &PreviousHandler);
|
||||
SignalHandlerInstalled = true;
|
||||
}
|
||||
|
||||
void uninstallSignalHandlers() {
|
||||
if (SignalHandlerInstalled) {
|
||||
sigaction(SIGSEGV, &PreviousHandler, nullptr);
|
||||
SignalHandlerInstalled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
|
||||
const gwp_asan::AllocationMetadata *Metadata,
|
||||
SegvBacktrace_t SegvBacktrace, Printf_t Printf,
|
||||
|
@ -205,7 +132,7 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
|
|||
// Maybe print the deallocation trace.
|
||||
if (__gwp_asan_is_deallocated(AllocMeta)) {
|
||||
uint64_t ThreadID = __gwp_asan_get_deallocation_thread_id(AllocMeta);
|
||||
if (ThreadID == kInvalidThreadID)
|
||||
if (ThreadID == gwp_asan::kInvalidThreadID)
|
||||
Printf("0x%zx was deallocated by thread <unknown> here:\n", ErrorPtr);
|
||||
else
|
||||
Printf("0x%zx was deallocated by thread %zu here:\n", ErrorPtr, ThreadID);
|
||||
|
@ -216,7 +143,7 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
|
|||
|
||||
// Print the allocation trace.
|
||||
uint64_t ThreadID = __gwp_asan_get_allocation_thread_id(AllocMeta);
|
||||
if (ThreadID == kInvalidThreadID)
|
||||
if (ThreadID == gwp_asan::kInvalidThreadID)
|
||||
Printf("0x%zx was allocated by thread <unknown> here:\n", ErrorPtr);
|
||||
else
|
||||
Printf("0x%zx was allocated by thread %zu here:\n", ErrorPtr, ThreadID);
|
||||
|
@ -224,5 +151,75 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
|
|||
AllocMeta, Trace, kMaximumStackFramesForCrashTrace);
|
||||
PrintBacktrace(Trace, TraceLength, Printf);
|
||||
}
|
||||
} // namespace crash_handler
|
||||
|
||||
struct sigaction PreviousHandler;
|
||||
bool SignalHandlerInstalled;
|
||||
gwp_asan::GuardedPoolAllocator *GPAForSignalHandler;
|
||||
Printf_t PrintfForSignalHandler;
|
||||
PrintBacktrace_t PrintBacktraceForSignalHandler;
|
||||
SegvBacktrace_t BacktraceForSignalHandler;
|
||||
|
||||
static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) {
|
||||
if (GPAForSignalHandler) {
|
||||
GPAForSignalHandler->stop();
|
||||
|
||||
dumpReport(reinterpret_cast<uintptr_t>(info->si_addr),
|
||||
GPAForSignalHandler->getAllocatorState(),
|
||||
GPAForSignalHandler->getMetadataRegion(),
|
||||
BacktraceForSignalHandler, PrintfForSignalHandler,
|
||||
PrintBacktraceForSignalHandler, ucontext);
|
||||
}
|
||||
|
||||
// Process any previous handlers.
|
||||
if (PreviousHandler.sa_flags & SA_SIGINFO) {
|
||||
PreviousHandler.sa_sigaction(sig, info, ucontext);
|
||||
} else if (PreviousHandler.sa_handler == SIG_DFL) {
|
||||
// If the previous handler was the default handler, cause a core dump.
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
raise(SIGSEGV);
|
||||
} else if (PreviousHandler.sa_handler == SIG_IGN) {
|
||||
// If the previous segv handler was SIGIGN, crash iff we were responsible
|
||||
// for the crash.
|
||||
if (__gwp_asan_error_is_mine(GPAForSignalHandler->getAllocatorState(),
|
||||
reinterpret_cast<uintptr_t>(info->si_addr))) {
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
raise(SIGSEGV);
|
||||
}
|
||||
} else {
|
||||
PreviousHandler.sa_handler(sig);
|
||||
}
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace segv_handler {
|
||||
|
||||
void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
|
||||
PrintBacktrace_t PrintBacktrace,
|
||||
SegvBacktrace_t SegvBacktrace) {
|
||||
assert(GPA && "GPA wasn't provided to installSignalHandlers.");
|
||||
assert(Printf && "Printf wasn't provided to installSignalHandlers.");
|
||||
assert(PrintBacktrace &&
|
||||
"PrintBacktrace wasn't provided to installSignalHandlers.");
|
||||
assert(SegvBacktrace &&
|
||||
"SegvBacktrace wasn't provided to installSignalHandlers.");
|
||||
GPAForSignalHandler = GPA;
|
||||
PrintfForSignalHandler = Printf;
|
||||
PrintBacktraceForSignalHandler = PrintBacktrace;
|
||||
BacktraceForSignalHandler = SegvBacktrace;
|
||||
|
||||
struct sigaction Action = {};
|
||||
Action.sa_sigaction = sigSegvHandler;
|
||||
Action.sa_flags = SA_SIGINFO;
|
||||
sigaction(SIGSEGV, &Action, &PreviousHandler);
|
||||
SignalHandlerInstalled = true;
|
||||
}
|
||||
|
||||
void uninstallSignalHandlers() {
|
||||
if (SignalHandlerInstalled) {
|
||||
sigaction(SIGSEGV, &PreviousHandler, nullptr);
|
||||
SignalHandlerInstalled = false;
|
||||
}
|
||||
}
|
||||
} // namespace segv_handler
|
||||
} // namespace gwp_asan
|
||||
|
|
|
@ -10,7 +10,7 @@ set(GWP_ASAN_UNITTEST_CFLAGS
|
|||
|
||||
file(GLOB GWP_ASAN_HEADERS ../*.h)
|
||||
set(GWP_ASAN_UNITTESTS
|
||||
optional/printf_sanitizer_common.cpp
|
||||
platform_specific/printf_sanitizer_common.cpp
|
||||
alignment.cpp
|
||||
backtrace.cpp
|
||||
basic.cpp
|
||||
|
|
|
@ -21,6 +21,7 @@ using Test = ::testing::Test;
|
|||
|
||||
#include "gwp_asan/guarded_pool_allocator.h"
|
||||
#include "gwp_asan/optional/backtrace.h"
|
||||
#include "gwp_asan/optional/printf.h"
|
||||
#include "gwp_asan/optional/segv_handler.h"
|
||||
#include "gwp_asan/options.h"
|
||||
|
||||
|
@ -30,7 +31,7 @@ namespace test {
|
|||
// their own signal-safe Printf function. In LLVM, we use
|
||||
// `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf
|
||||
// for this purpose.
|
||||
crash_handler::Printf_t getPrintfFunction();
|
||||
Printf_t getPrintfFunction();
|
||||
|
||||
// First call returns true, all the following calls return false.
|
||||
bool OnlyOnce();
|
||||
|
@ -86,19 +87,19 @@ public:
|
|||
gwp_asan::options::Options Opts;
|
||||
Opts.setDefaults();
|
||||
|
||||
Opts.Backtrace = gwp_asan::options::getBacktraceFunction();
|
||||
Opts.Backtrace = gwp_asan::backtrace::getBacktraceFunction();
|
||||
Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce();
|
||||
GPA.init(Opts);
|
||||
|
||||
gwp_asan::crash_handler::installSignalHandlers(
|
||||
gwp_asan::segv_handler::installSignalHandlers(
|
||||
&GPA, gwp_asan::test::getPrintfFunction(),
|
||||
gwp_asan::options::getPrintBacktraceFunction(),
|
||||
gwp_asan::crash_handler::getSegvBacktraceFunction());
|
||||
gwp_asan::backtrace::getPrintBacktraceFunction(),
|
||||
gwp_asan::backtrace::getSegvBacktraceFunction());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
GPA.uninitTestOnly();
|
||||
gwp_asan::crash_handler::uninstallSignalHandlers();
|
||||
gwp_asan::segv_handler::uninstallSignalHandlers();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -6,15 +6,14 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gwp_asan/optional/segv_handler.h"
|
||||
#include "gwp_asan/optional/printf.h"
|
||||
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
|
||||
namespace gwp_asan {
|
||||
namespace test {
|
||||
// This printf-function getter allows other platforms (e.g. Android) to define
|
||||
// their own signal-safe Printf function. In LLVM, we use
|
||||
// `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf
|
||||
// for this purpose.
|
||||
crash_handler::Printf_t getPrintfFunction() { return __sanitizer::Printf; }
|
||||
}; // namespace test
|
||||
}; // namespace gwp_asan
|
||||
|
||||
Printf_t getPrintfFunction() { return __sanitizer::Printf; }
|
||||
|
||||
} // namespace test
|
||||
} // namespace gwp_asan
|
|
@ -674,14 +674,14 @@ void initScudo() {
|
|||
#ifdef GWP_ASAN_HOOKS
|
||||
gwp_asan::options::initOptions();
|
||||
gwp_asan::options::Options &Opts = gwp_asan::options::getOptions();
|
||||
Opts.Backtrace = gwp_asan::options::getBacktraceFunction();
|
||||
Opts.Backtrace = gwp_asan::backtrace::getBacktraceFunction();
|
||||
GuardedAlloc.init(Opts);
|
||||
|
||||
if (Opts.InstallSignalHandlers)
|
||||
gwp_asan::crash_handler::installSignalHandlers(
|
||||
gwp_asan::segv_handler::installSignalHandlers(
|
||||
&GuardedAlloc, __sanitizer::Printf,
|
||||
gwp_asan::options::getPrintBacktraceFunction(),
|
||||
gwp_asan::crash_handler::getSegvBacktraceFunction());
|
||||
gwp_asan::backtrace::getPrintBacktraceFunction(),
|
||||
gwp_asan::backtrace::getSegvBacktraceFunction());
|
||||
#endif // GWP_ASAN_HOOKS
|
||||
}
|
||||
|
||||
|
|
|
@ -198,13 +198,14 @@ public:
|
|||
// Allocator::disable calling GWPASan.disable). Disable GWP-ASan's atfork
|
||||
// handler.
|
||||
Opt.InstallForkHandlers = false;
|
||||
Opt.Backtrace = gwp_asan::options::getBacktraceFunction();
|
||||
Opt.Backtrace = gwp_asan::backtrace::getBacktraceFunction();
|
||||
GuardedAlloc.init(Opt);
|
||||
|
||||
if (Opt.InstallSignalHandlers)
|
||||
gwp_asan::crash_handler::installSignalHandlers(
|
||||
&GuardedAlloc, Printf, gwp_asan::options::getPrintBacktraceFunction(),
|
||||
gwp_asan::crash_handler::getSegvBacktraceFunction());
|
||||
gwp_asan::segv_handler::installSignalHandlers(
|
||||
&GuardedAlloc, Printf,
|
||||
gwp_asan::backtrace::getPrintBacktraceFunction(),
|
||||
gwp_asan::backtrace::getSegvBacktraceFunction());
|
||||
#endif // GWP_ASAN_HOOKS
|
||||
}
|
||||
|
||||
|
@ -219,7 +220,7 @@ public:
|
|||
Primary.unmapTestOnly();
|
||||
#ifdef GWP_ASAN_HOOKS
|
||||
if (getFlags()->GWP_ASAN_InstallSignalHandlers)
|
||||
gwp_asan::crash_handler::uninstallSignalHandlers();
|
||||
gwp_asan::segv_handler::uninstallSignalHandlers();
|
||||
GuardedAlloc.uninitTestOnly();
|
||||
#endif // GWP_ASAN_HOOKS
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue