Skip to content

Commit 632562d

Browse files
author
git apple-llvm automerger
committed
Merge commit '9ed1d14ce533' from apple/master into swift/master-next
2 parents ec00c54 + 9ed1d14 commit 632562d

File tree

9 files changed

+99
-23
lines changed

9 files changed

+99
-23
lines changed

compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
2323
return backtrace(reinterpret_cast<void **>(TraceBuffer), Size);
2424
}
2525

26+
// We don't need any custom handling for the Segv backtrace - the libc unwinder
27+
// has no problems with unwinding through a signal handler. Force inlining here
28+
// to avoid the additional frame.
29+
GWP_ASAN_ALWAYS_INLINE size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size,
30+
void * /*Context*/) {
31+
return Backtrace(TraceBuffer, Size);
32+
}
33+
2634
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
2735
gwp_asan::crash_handler::Printf_t Printf) {
2836
if (TraceLength == 0) {
@@ -53,4 +61,8 @@ crash_handler::PrintBacktrace_t getPrintBacktraceFunction() {
5361
return PrintBacktrace;
5462
}
5563
} // namespace options
64+
65+
namespace crash_handler {
66+
SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
67+
} // namespace crash_handler
5668
} // namespace gwp_asan

compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,45 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
2222
void *context,
2323
bool request_fast,
2424
u32 max_depth) {
25-
if (!StackTrace::WillUseFastUnwind(request_fast)) {
26-
return Unwind(max_depth, pc, bp, context, 0, 0, request_fast);
27-
}
28-
Unwind(max_depth, pc, 0, context, 0, 0, false);
25+
if (!StackTrace::WillUseFastUnwind(request_fast))
26+
return Unwind(max_depth, pc, 0, context, 0, 0, false);
27+
28+
uptr top = 0;
29+
uptr bottom = 0;
30+
GetThreadStackTopAndBottom(/*at_initialization*/ false, &top, &bottom);
31+
32+
return Unwind(max_depth, pc, bp, context, top, bottom, request_fast);
2933
}
3034

3135
namespace {
32-
size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
36+
size_t BacktraceCommon(uintptr_t *TraceBuffer, size_t Size, void *Context) {
37+
// Use the slow sanitizer unwinder in the segv handler. Fast frame pointer
38+
// unwinders can end up dropping frames because the kernel sigreturn() frame's
39+
// return address is the return address at time of fault. This has the result
40+
// of never actually capturing the PC where the signal was raised.
41+
bool UseFastUnwind = (Context == nullptr);
42+
3343
__sanitizer::BufferedStackTrace Trace;
3444
Trace.Reset();
3545
if (Size > __sanitizer::kStackTraceMax)
3646
Size = __sanitizer::kStackTraceMax;
3747

3848
Trace.Unwind((__sanitizer::uptr)__builtin_return_address(0),
39-
(__sanitizer::uptr)__builtin_frame_address(0),
40-
/* ucontext */ nullptr,
41-
/* fast unwind */ true, Size - 1);
49+
(__sanitizer::uptr)__builtin_frame_address(0), Context,
50+
UseFastUnwind, Size - 1);
4251

4352
memcpy(TraceBuffer, Trace.trace, Trace.size * sizeof(uintptr_t));
4453
return Trace.size;
4554
}
4655

56+
size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) {
57+
return BacktraceCommon(TraceBuffer, Size, nullptr);
58+
}
59+
60+
size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size, void *Context) {
61+
return BacktraceCommon(TraceBuffer, Size, Context);
62+
}
63+
4764
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
4865
gwp_asan::crash_handler::Printf_t Printf) {
4966
__sanitizer::StackTrace StackTrace;
@@ -77,4 +94,8 @@ crash_handler::PrintBacktrace_t getPrintBacktraceFunction() {
7794
return PrintBacktrace;
7895
}
7996
} // namespace options
97+
98+
namespace crash_handler {
99+
SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
100+
} // namespace crash_handler
80101
} // namespace gwp_asan

compiler-rt/lib/gwp_asan/optional/segv_handler.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength,
5959
// without any symbolization.
6060
PrintBacktrace_t getBasicPrintBacktraceFunction();
6161

62+
// Returns a function pointer to a backtrace function that's suitable for
63+
// unwinding through a signal handler. This is important primarily for frame-
64+
// pointer based unwinders, DWARF or other unwinders can simply provide the
65+
// normal backtrace function as the implementation here. On POSIX, SignalContext
66+
// should be the `ucontext_t` from the signal handler.
67+
typedef size_t (*SegvBacktrace_t)(uintptr_t *TraceBuffer, size_t Size,
68+
void *SignalContext);
69+
SegvBacktrace_t getSegvBacktraceFunction();
70+
6271
// Install the SIGSEGV crash handler for printing use-after-free and heap-
6372
// buffer-{under|over}flow exceptions if the user asked for it. This is platform
6473
// specific as even though POSIX and Windows both support registering handlers
@@ -67,14 +76,14 @@ PrintBacktrace_t getBasicPrintBacktraceFunction();
6776
// before this function.
6877
void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
6978
PrintBacktrace_t PrintBacktrace,
70-
options::Backtrace_t Backtrace);
79+
SegvBacktrace_t SegvBacktrace);
7180

7281
void uninstallSignalHandlers();
7382

7483
void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
7584
const gwp_asan::AllocationMetadata *Metadata,
76-
options::Backtrace_t Backtrace, Printf_t Printf,
77-
PrintBacktrace_t PrintBacktrace);
85+
SegvBacktrace_t SegvBacktrace, Printf_t Printf,
86+
PrintBacktrace_t PrintBacktrace, void *Context);
7887
} // namespace crash_handler
7988
} // namespace gwp_asan
8089

compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ using gwp_asan::Error;
2323
using gwp_asan::GuardedPoolAllocator;
2424
using gwp_asan::crash_handler::PrintBacktrace_t;
2525
using gwp_asan::crash_handler::Printf_t;
26-
using gwp_asan::options::Backtrace_t;
26+
using gwp_asan::crash_handler::SegvBacktrace_t;
2727

2828
struct sigaction PreviousHandler;
2929
bool SignalHandlerInstalled;
3030
gwp_asan::GuardedPoolAllocator *GPAForSignalHandler;
3131
Printf_t PrintfForSignalHandler;
3232
PrintBacktrace_t PrintBacktraceForSignalHandler;
33-
Backtrace_t BacktraceForSignalHandler;
33+
SegvBacktrace_t BacktraceForSignalHandler;
3434

3535
static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) {
3636
if (GPAForSignalHandler) {
@@ -40,7 +40,7 @@ static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) {
4040
reinterpret_cast<uintptr_t>(info->si_addr),
4141
GPAForSignalHandler->getAllocatorState(),
4242
GPAForSignalHandler->getMetadataRegion(), BacktraceForSignalHandler,
43-
PrintfForSignalHandler, PrintBacktraceForSignalHandler);
43+
PrintfForSignalHandler, PrintBacktraceForSignalHandler, ucontext);
4444
}
4545

4646
// Process any previous handlers.
@@ -138,11 +138,11 @@ PrintBacktrace_t getBasicPrintBacktraceFunction() {
138138

139139
void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
140140
PrintBacktrace_t PrintBacktrace,
141-
options::Backtrace_t Backtrace) {
141+
SegvBacktrace_t SegvBacktrace) {
142142
GPAForSignalHandler = GPA;
143143
PrintfForSignalHandler = Printf;
144144
PrintBacktraceForSignalHandler = PrintBacktrace;
145-
BacktraceForSignalHandler = Backtrace;
145+
BacktraceForSignalHandler = SegvBacktrace;
146146

147147
struct sigaction Action;
148148
Action.sa_sigaction = sigSegvHandler;
@@ -160,8 +160,8 @@ void uninstallSignalHandlers() {
160160

161161
void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
162162
const gwp_asan::AllocationMetadata *Metadata,
163-
options::Backtrace_t Backtrace, Printf_t Printf,
164-
PrintBacktrace_t PrintBacktrace) {
163+
SegvBacktrace_t SegvBacktrace, Printf_t Printf,
164+
PrintBacktrace_t PrintBacktrace, void *Context) {
165165
assert(State && "dumpReport missing Allocator State.");
166166
assert(Metadata && "dumpReport missing Metadata.");
167167
assert(Printf && "dumpReport missing Printf.");
@@ -194,7 +194,8 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
194194
// Print the fault backtrace.
195195
static constexpr unsigned kMaximumStackFramesForCrashTrace = 512;
196196
uintptr_t Trace[kMaximumStackFramesForCrashTrace];
197-
size_t TraceLength = Backtrace(Trace, kMaximumStackFramesForCrashTrace);
197+
size_t TraceLength =
198+
SegvBacktrace(Trace, kMaximumStackFramesForCrashTrace, Context);
198199

199200
PrintBacktrace(Trace, TraceLength, Printf);
200201

compiler-rt/lib/gwp_asan/tests/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ set(GWP_ASAN_UNITTEST_CFLAGS
55
${COMPILER_RT_GTEST_CFLAGS}
66
-I${COMPILER_RT_SOURCE_DIR}/lib/
77
-O2
8-
-g)
8+
-g
9+
-fno-omit-frame-pointer)
910

1011
file(GLOB GWP_ASAN_HEADERS ../*.h)
1112
set(GWP_ASAN_UNITTESTS

compiler-rt/lib/gwp_asan/tests/harness.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ class BacktraceGuardedPoolAllocator : public ::testing::Test {
8686

8787
gwp_asan::crash_handler::installSignalHandlers(
8888
&GPA, gwp_asan::test::getPrintfFunction(),
89-
gwp_asan::options::getPrintBacktraceFunction(), Opts.Backtrace);
89+
gwp_asan::options::getPrintBacktraceFunction(),
90+
gwp_asan::crash_handler::getSegvBacktraceFunction());
9091
}
9192

9293
void TearDown() override {

compiler-rt/lib/scudo/scudo_allocator.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
# include "gwp_asan/guarded_pool_allocator.h"
3030
# include "gwp_asan/optional/backtrace.h"
3131
# include "gwp_asan/optional/options_parser.h"
32+
#include "gwp_asan/optional/segv_handler.h"
3233
#endif // GWP_ASAN_HOOKS
3334

3435
#include <errno.h>
@@ -679,7 +680,8 @@ void initScudo() {
679680
if (Opts.InstallSignalHandlers)
680681
gwp_asan::crash_handler::installSignalHandlers(
681682
&GuardedAlloc, __sanitizer::Printf,
682-
gwp_asan::options::getPrintBacktraceFunction(), Opts.Backtrace);
683+
gwp_asan::options::getPrintBacktraceFunction(),
684+
gwp_asan::crash_handler::getSegvBacktraceFunction());
683685
#endif // GWP_ASAN_HOOKS
684686
}
685687

compiler-rt/lib/scudo/standalone/combined.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ class Allocator {
192192
if (Opt.InstallSignalHandlers)
193193
gwp_asan::crash_handler::installSignalHandlers(
194194
&GuardedAlloc, Printf, gwp_asan::options::getPrintBacktraceFunction(),
195-
Opt.Backtrace);
195+
gwp_asan::crash_handler::getSegvBacktraceFunction());
196196
#endif // GWP_ASAN_HOOKS
197197
}
198198

compiler-rt/test/gwp_asan/backtrace.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// REQUIRES: gwp_asan
2+
// RUN: %clang_gwp_asan %s -g -o %t
3+
// RUN: %expect_crash %t 2>&1 | FileCheck %s
4+
5+
#include <stdlib.h>
6+
7+
__attribute__((noinline)) void *allocate_mem() { return malloc(1); }
8+
9+
__attribute__((noinline)) void free_mem(void *ptr) { free(ptr); }
10+
11+
__attribute__((noinline)) void touch_mem(void *ptr) {
12+
volatile char sink = *((volatile char *)ptr);
13+
}
14+
15+
// CHECK: Use After Free
16+
// CHECK: touch_mem
17+
// CHECK: was deallocated
18+
// CHECK: free_mem
19+
// CHECK: was allocated
20+
// CHECK: allocate_mem
21+
22+
int main() {
23+
for (unsigned i = 0; i < 0x10000; ++i) {
24+
void *ptr = allocate_mem();
25+
free_mem(ptr);
26+
touch_mem(ptr);
27+
}
28+
return 0;
29+
}

0 commit comments

Comments
 (0)