[compiler-rt] r322324 - [hwasan] Stack instrumentation.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 11 14:53:30 PST 2018


Author: eugenis
Date: Thu Jan 11 14:53:30 2018
New Revision: 322324

URL: http://llvm.org/viewvc/llvm-project?rev=322324&view=rev
Log:
[hwasan] Stack instrumentation.

Summary:
Very basic stack instrumentation using tagged pointers.
Tag for N'th alloca in a function is built as XOR of:
 * base tag for the function, which is just some bits of SP (poor
   man's random)
 * small constant which is a function of N.

Allocas are aligned to 16 bytes. On every ReturnInst allocas are
re-tagged to catch use-after-return.

This implementation has a bunch of issues that will be taken care of
later:
1. lifetime intrinsics referring to tagged pointers are not
   recognized in SDAG. This effectively disables stack coloring.
2. Generated code is quite inefficient. There is one extra
   instruction at each memory access that adds the base tag to the
   untagged alloca address. It would be better to keep tagged SP in a
   callee-saved register and address allocas as an offset of that XOR
   retag, but that needs better coordination between hwasan
   instrumentation pass and prologue/epilogue insertion.
3. Lifetime instrinsics are ignored and use-after-scope is not
   implemented. This would be harder to do than in ASan, because we
   need to use a differently tagged pointer depending on which
   lifetime.start / lifetime.end the current instruction is dominated
   / post-dominated.

Reviewers: kcc, alekseyshl

Subscribers: srhines, kubamracek, javed.absar, hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D41602

Added:
    compiler-rt/trunk/test/hwasan/TestCases/stack-oob.cc
    compiler-rt/trunk/test/hwasan/TestCases/stack-uar.cc
Modified:
    compiler-rt/trunk/lib/hwasan/hwasan.cc
    compiler-rt/trunk/lib/hwasan/hwasan.h
    compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc
    compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
    compiler-rt/trunk/lib/hwasan/hwasan_linux.cc

Modified: compiler-rt/trunk/lib/hwasan/hwasan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.cc?rev=322324&r1=322323&r2=322324&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.cc Thu Jan 11 14:53:30 2018
@@ -359,6 +359,10 @@ void __hwasan_store16_noabort(uptr p) {
   CheckAddress<ErrorAction::Recover, AccessType::Store, 4>(p);
 }
 
+void __hwasan_tag_memory(uptr p, u8 tag, uptr sz) {
+  TagMemoryAligned(p, sz, tag);
+}
+
 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
 extern "C" {
 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE

Modified: compiler-rt/trunk/lib/hwasan/hwasan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.h?rev=322324&r1=322323&r2=322324&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.h Thu Jan 11 14:53:30 2018
@@ -40,7 +40,7 @@ const uptr kShadowAlignment = 1UL << kSh
 #define MEM_TO_SHADOW(mem) ((uptr)(mem) >> kShadowScale)
 #define SHADOW_TO_MEM(shadow) ((uptr)(shadow) << kShadowScale)
 
-#define MEM_IS_APP(mem) true
+#define MEM_IS_APP(mem) MemIsApp((uptr)(mem))
 
 // TBI (Top Byte Ignore) feature of AArch64: bits [63:56] are ignored in address
 // translation and can be used to store a tag.
@@ -69,6 +69,8 @@ extern int hwasan_inited;
 extern bool hwasan_init_is_running;
 extern int hwasan_report_count;
 
+bool MemIsApp(uptr p);
+
 bool ProtectRange(uptr beg, uptr end);
 bool InitShadow();
 char *GetProcSelfMaps();

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc?rev=322324&r1=322323&r2=322324&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc Thu Jan 11 14:53:30 2018
@@ -427,6 +427,15 @@ int OnExit() {
     *begin = *end = 0;                                                         \
   }
 
+#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
+  {                                                       \
+    COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size);  \
+    if (common_flags()->intercept_intrin &&               \
+        MEM_IS_APP(GetAddressFromPointer(dst)))           \
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size);     \
+    return REAL(memset)(dst, v, size);                    \
+  }
+
 #include "sanitizer_common/sanitizer_platform_interceptors.h"
 #include "sanitizer_common/sanitizer_common_interceptors.inc"
 #include "sanitizer_common/sanitizer_signal_interceptors.inc"

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h?rev=322324&r1=322323&r2=322324&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h Thu Jan 11 14:53:30 2018
@@ -83,6 +83,9 @@ void __hwasan_store8_noabort(uptr);
 SANITIZER_INTERFACE_ATTRIBUTE
 void __hwasan_store16_noabort(uptr);
 
+SANITIZER_INTERFACE_ATTRIBUTE
+void __hwasan_tag_memory(uptr p, u8 tag, uptr sz);
+
 // Returns the offset of the first tag mismatch or -1 if the whole range is
 // good.
 SANITIZER_INTERFACE_ATTRIBUTE

Modified: compiler-rt/trunk/lib/hwasan/hwasan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_linux.cc?rev=322324&r1=322323&r2=322324&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_linux.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_linux.cc Thu Jan 11 14:53:30 2018
@@ -74,20 +74,24 @@ static void ProtectGap(uptr addr, uptr s
   Die();
 }
 
+// LowMem covers as much of the first 4GB as possible.
+const uptr kLowMemEnd = 1UL<<32;
+const uptr kLowShadowEnd = kLowMemEnd >> kShadowScale;
+const uptr kLowShadowStart = kLowShadowEnd >> kShadowScale;
+static uptr kHighShadowStart;
+static uptr kHighShadowEnd;
+static uptr kHighMemStart;
+
 bool InitShadow() {
   const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
 
-  // LowMem covers as much of the first 4GB as possible.
-  const uptr kLowMemEnd = 1UL<<32;
-  const uptr kLowShadowEnd = kLowMemEnd >> kShadowScale;
-  const uptr kLowShadowStart = kLowShadowEnd >> kShadowScale;
 
   // HighMem covers the upper part of the address space.
-  const uptr kHighShadowEnd = (maxVirtualAddress >> kShadowScale) + 1;
-  const uptr kHighShadowStart = Max(kLowMemEnd, kHighShadowEnd >> kShadowScale);
+  kHighShadowEnd = (maxVirtualAddress >> kShadowScale) + 1;
+  kHighShadowStart = Max(kLowMemEnd, kHighShadowEnd >> kShadowScale);
   CHECK(kHighShadowStart < kHighShadowEnd);
 
-  const uptr kHighMemStart = kHighShadowStart << kShadowScale;
+  kHighMemStart = kHighShadowStart << kShadowScale;
   CHECK(kHighShadowEnd <= kHighMemStart);
 
   if (Verbosity()) {
@@ -120,6 +124,11 @@ bool InitShadow() {
   return true;
 }
 
+bool MemIsApp(uptr p) {
+  CHECK(GetTagFromPointer(p) == 0);
+  return p >= kHighMemStart || (p >= kLowShadowEnd && p < kLowMemEnd);
+}
+
 static void HwasanAtExit(void) {
   if (flags()->print_stats && (flags()->atexit || hwasan_report_count > 0))
     ReportStats();

Added: compiler-rt/trunk/test/hwasan/TestCases/stack-oob.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/stack-oob.cc?rev=322324&view=auto
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/stack-oob.cc (added)
+++ compiler-rt/trunk/test/hwasan/TestCases/stack-oob.cc Thu Jan 11 14:53:30 2018
@@ -0,0 +1,25 @@
+// RUN: %clangxx_hwasan -DSIZE=16 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_hwasan -DSIZE=64 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_hwasan -DSIZE=0x1000 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: stable-runtime
+
+#include <stdlib.h>
+#include <sanitizer/hwasan_interface.h>
+
+__attribute__((noinline))
+int f() {
+  char z[SIZE];
+  char *volatile p = z;
+  return p[SIZE];
+}
+
+int main() {
+  return f();
+  // CHECK: READ of size 1 at
+  // CHECK: #0 {{.*}} in f{{.*}}stack-oob.cc:14
+
+  // CHECK: HWAddressSanitizer can not describe address in more detail.
+
+  // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in f
+}

Added: compiler-rt/trunk/test/hwasan/TestCases/stack-uar.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/stack-uar.cc?rev=322324&view=auto
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/stack-uar.cc (added)
+++ compiler-rt/trunk/test/hwasan/TestCases/stack-uar.cc Thu Jan 11 14:53:30 2018
@@ -0,0 +1,23 @@
+// RUN: %clangxx_hwasan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: stable-runtime
+
+#include <stdlib.h>
+#include <sanitizer/hwasan_interface.h>
+
+__attribute__((noinline))
+char *f() {
+  char z[0x1000];
+  char *volatile p = z;
+  return p;
+}
+
+int main() {
+  return *f();
+  // CHECK: READ of size 1 at
+  // CHECK: #0 {{.*}} in main{{.*}}stack-uar.cc:16
+
+  // CHECK: HWAddressSanitizer can not describe address in more detail.
+
+  // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main
+}




More information about the llvm-commits mailing list