[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