[compiler-rt] r201673 - [asan] A different way of detectinb stack overflow.
Evgeniy Stepanov
eugeni.stepanov at gmail.com
Wed Feb 19 05:40:42 PST 2014
Author: eugenis
Date: Wed Feb 19 07:40:41 2014
New Revision: 201673
URL: http://llvm.org/viewvc/llvm-project?rev=201673&view=rev
Log:
[asan] A different way of detectinb stack overflow.
Instead of checking stack limits that are not well defined for the main thread,
we rely on siginfo::si_code and distance from SP.
Modified:
compiler-rt/trunk/lib/asan/asan_posix.cc
compiler-rt/trunk/lib/asan/asan_report.cc
compiler-rt/trunk/lib/asan/asan_report.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
Modified: compiler-rt/trunk/lib/asan/asan_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_posix.cc?rev=201673&r1=201672&r2=201673&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_posix.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_posix.cc Wed Feb 19 07:40:41 2014
@@ -34,11 +34,23 @@ namespace __asan {
void AsanOnSIGSEGV(int, void *siginfo, void *context) {
uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
+ int code = (int)((siginfo_t*)siginfo)->si_code;
// Write the first message using the bullet-proof write.
if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die();
uptr pc, sp, bp;
GetPcSpBp(context, &pc, &sp, &bp);
- ReportSIGSEGV(pc, sp, bp, context, addr);
+
+ // Access at a reasonable offset above SP, or slightly below it (to account
+ // for x86_64 redzone, ARM push of multiple registers, etc) is probably a
+ // stack overflow.
+ // We also check si_code to filter out SEGV caused by something else other
+ // then hitting the guard page or unmapped memory, like, for example,
+ // unaligned memory access.
+ if (addr + 128 > sp && addr < sp + 0xFFFF &&
+ (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR))
+ ReportStackOverflow(pc, sp, bp, context, addr);
+ else
+ ReportSIGSEGV(pc, sp, bp, context, addr);
}
// ---------------------- TSD ---------------- {{{1
Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=201673&r1=201672&r2=201673&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Wed Feb 19 07:40:41 2014
@@ -568,40 +568,35 @@ class ScopedInErrorReport {
}
};
-static bool IsStackOverflow(uptr addr, uptr sp) {
- uptr stack_frame_bottom = sp;
- // x86_64 stack redzone: leaf functions can access up to 128 bytes below SP.
- // ARM has push-multiple instruction that stores up to 64(?) bytes below SP.
- stack_frame_bottom -= 128;
-
- // Access below SP (minus redzone) is probably something else (like stack of
- // another thread).
- if (addr < stack_frame_bottom)
- return false;
-
- AsanThread *t = GetCurrentThread();
- // Anything below stack_bottom, but not too far away is a stack overflow.
- // Bottom 4k may be a guard page. Treat it as stack-overflow as well.
- return addr < t->stack_bottom() + GetPageSizeCached() &&
- addr > t->stack_bottom() - 0xFFFF;
+void ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
+ ScopedInErrorReport in_report;
+ Decorator d;
+ Printf("%s", d.Warning());
+ Report(
+ "ERROR: AddressSanitizer: stack-overflow on address %p"
+ " (pc %p sp %p bp %p T%d)\n",
+ (void *)addr, (void *)pc, (void *)sp, (void *)bp,
+ GetCurrentTidOrInvalid());
+ Printf("%s", d.EndWarning());
+ GET_STACK_TRACE_SIGNAL(pc, bp, context);
+ stack.Print();
+ ReportErrorSummary("stack-overflow", &stack);
}
void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr) {
ScopedInErrorReport in_report;
Decorator d;
Printf("%s", d.Warning());
- bool stack_overflow = IsStackOverflow(addr, sp);
Report(
- "ERROR: AddressSanitizer: %s %p"
+ "ERROR: AddressSanitizer: SEGV on unknown address %p"
" (pc %p sp %p bp %p T%d)\n",
- stack_overflow ? "stack-overflow on address" : "SEGV on unknown address",
(void *)addr, (void *)pc, (void *)sp, (void *)bp,
GetCurrentTidOrInvalid());
Printf("%s", d.EndWarning());
GET_STACK_TRACE_SIGNAL(pc, bp, context);
stack.Print();
Printf("AddressSanitizer can not provide additional info.\n");
- ReportErrorSummary(stack_overflow ? "stack-overflow" : "SEGV", &stack);
+ ReportErrorSummary("SEGV", &stack);
}
void ReportDoubleFree(uptr addr, StackTrace *free_stack) {
Modified: compiler-rt/trunk/lib/asan/asan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.h?rev=201673&r1=201672&r2=201673&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Wed Feb 19 07:40:41 2014
@@ -33,6 +33,8 @@ void DescribeThread(AsanThreadContext *c
// Different kinds of error reports.
void NORETURN
+ ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
+void NORETURN
ReportSIGSEGV(uptr pc, uptr sp, uptr bp, void *context, uptr addr);
void NORETURN ReportDoubleFree(uptr addr, StackTrace *free_stack);
void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *free_stack);
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc?rev=201673&r1=201672&r2=201673&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc Wed Feb 19 07:40:41 2014
@@ -772,10 +772,13 @@ namespace __sanitizer {
const int errno_EINVAL = EINVAL;
// EOWNERDEAD is not present in some older platforms.
#if defined(EOWNERDEAD)
- extern const int errno_EOWNERDEAD = EOWNERDEAD;
+ const int errno_EOWNERDEAD = EOWNERDEAD;
#else
- extern const int errno_EOWNERDEAD = -1;
+ const int errno_EOWNERDEAD = -1;
#endif
+
+ const int si_SEGV_MAPERR = SEGV_MAPERR;
+ const int si_SEGV_ACCERR = SEGV_ACCERR;
} // namespace __sanitizer
COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h?rev=201673&r1=201672&r2=201673&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h Wed Feb 19 07:40:41 2014
@@ -1054,6 +1054,9 @@ namespace __sanitizer {
extern const int errno_EINVAL;
extern const int errno_EOWNERDEAD;
+
+ extern const int si_SEGV_MAPERR;
+ extern const int si_SEGV_ACCERR;
} // namespace __sanitizer
#define CHECK_TYPE_SIZE(TYPE) \
More information about the llvm-commits
mailing list