[compiler-rt] r351730 - [HWASAN] Improve tag mismatch diagnostics

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 21 01:51:10 PST 2019


Author: evgeny777
Date: Mon Jan 21 01:51:10 2019
New Revision: 351730

URL: http://llvm.org/viewvc/llvm-project?rev=351730&view=rev
Log:
[HWASAN] Improve tag mismatch diagnostics

Reports correct size and tags when either size is not power of two
or offset to bad granule is not zero.

Differential revision: https://reviews.llvm.org/D56603

Modified:
    compiler-rt/trunk/lib/hwasan/hwasan.cc
    compiler-rt/trunk/lib/hwasan/hwasan_checks.h
    compiler-rt/trunk/lib/hwasan/hwasan_report.cc
    compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c

Modified: compiler-rt/trunk/lib/hwasan/hwasan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.cc?rev=351730&r1=351729&r2=351730&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.cc Mon Jan 21 01:51:10 2019
@@ -336,14 +336,14 @@ sptr __hwasan_test_shadow(const void *p,
   if (sz == 0)
     return -1;
   tag_t ptr_tag = GetTagFromPointer((uptr)p);
-  if (ptr_tag == 0)
-    return -1;
   uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
   uptr shadow_first = MemToShadow(ptr_raw);
   uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
   for (uptr s = shadow_first; s <= shadow_last; ++s)
-    if (*(tag_t*)s != ptr_tag)
-      return ShadowToMem(s) - ptr_raw;
+    if (*(tag_t *)s != ptr_tag) {
+      sptr offset = ShadowToMem(s) - ptr_raw;
+      return offset < 0 ? 0 : offset;
+    }
   return -1;
 }
 

Modified: compiler-rt/trunk/lib/hwasan/hwasan_checks.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_checks.h?rev=351730&r1=351729&r2=351730&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_checks.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_checks.h Mon Jan 21 01:51:10 2019
@@ -14,6 +14,7 @@
 #define HWASAN_CHECKS_H
 
 #include "hwasan_mapping.h"
+#include "sanitizer_common/sanitizer_common.h"
 
 namespace __hwasan {
 template <unsigned X>
@@ -22,8 +23,8 @@ __attribute__((always_inline)) static vo
   (void)p;
   // 0x900 is added to do not interfere with the kernel use of lower values of
   // brk immediate.
-  // FIXME: Add a constraint to put the pointer into x0, the same as x86 branch.
-  asm("brk %0\n\t" ::"n"(0x900 + X));
+  register uptr x0 asm("x0") = p;
+  asm("brk %1\n\t" ::"r"(x0), "n"(0x900 + X));
 #elif defined(__x86_64__)
   // INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes
   // total. The pointer is passed via rdi.
@@ -41,6 +42,25 @@ __attribute__((always_inline)) static vo
   // __builtin_unreachable();
 }
 
+// Version with access size which is not power of 2
+template <unsigned X>
+__attribute__((always_inline)) static void SigTrap(uptr p, uptr size) {
+#if defined(__aarch64__)
+  register uptr x0 asm("x0") = p;
+  register uptr x1 asm("x1") = size;
+  asm("brk %2\n\t" ::"r"(x0), "r"(x1), "n"(0x900 + X));
+#elif defined(__x86_64__)
+  // Size is stored in rsi.
+  asm volatile(
+      "int3\n"
+      "nopl %c0(%%rax)\n" ::"n"(0x40 + X),
+      "D"(p), "S"(size));
+#else
+  __builtin_trap();
+#endif
+  // __builtin_unreachable();
+}
+
 enum class ErrorAction { Abort, Recover };
 enum class AccessType { Load, Store };
 
@@ -69,7 +89,7 @@ __attribute__((always_inline, nodebug))
   for (tag_t *t = shadow_first; t <= shadow_last; ++t)
     if (UNLIKELY(ptr_tag != *t)) {
       SigTrap<0x20 * (EA == ErrorAction::Recover) +
-              0x10 * (AT == AccessType::Store) + 0xf>(p);
+              0x10 * (AT == AccessType::Store) + 0xf>(p, sz);
       if (EA == ErrorAction::Abort)
         __builtin_unreachable();
     }

Modified: compiler-rt/trunk/lib/hwasan/hwasan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_report.cc?rev=351730&r1=351729&r2=351730&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_report.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_report.cc Mon Jan 21 01:51:10 2019
@@ -399,13 +399,21 @@ void ReportTagMismatch(StackTrace *stack
 
   Thread *t = GetCurrentThread();
 
+  sptr offset =
+      __hwasan_test_shadow(reinterpret_cast<void *>(tagged_addr), access_size);
+  CHECK(offset >= 0 && offset < static_cast<sptr>(access_size));
   tag_t ptr_tag = GetTagFromPointer(tagged_addr);
-  tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
+  tag_t *tag_ptr =
+      reinterpret_cast<tag_t *>(MemToShadow(untagged_addr + offset));
   tag_t mem_tag = *tag_ptr;
+
   Printf("%s", d.Access());
   Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n",
          is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
          mem_tag, t->unique_id());
+  if (offset != 0)
+    Printf("Invalid access starting at offset [%zu, %zu)\n", offset,
+           Min(access_size, static_cast<uptr>(offset) + (1 << kShadowScale)));
   Printf("%s", d.Default());
 
   stack->Print();

Modified: compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c?rev=351730&r1=351729&r2=351730&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c (original)
+++ compiler-rt/trunk/test/hwasan/TestCases/mem-intrinsics.c Mon Jan 21 01:51:10 2019
@@ -10,8 +10,8 @@
 #include <unistd.h>
 
 int main() {
-  char Q[16];
-  char P[16];
+  char Q[16] __attribute__((aligned(256)));
+  char P[16] __attribute__((aligned(256)));
 #if TEST_NO == 1
   memset(Q, 0, 32);
 #elif TEST_NO == 2
@@ -21,15 +21,17 @@ int main() {
 #endif
   write(STDOUT_FILENO, "recovered\n", 10);
   // WRITE: ERROR: HWAddressSanitizer: tag-mismatch on address
-  // WRITE: WRITE {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
+  // WRITE: WRITE of size 32 at {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
+  // WRITE: Invalid access starting at offset [16, 32)
   // WRITE: Memory tags around the buggy address (one tag corresponds to 16 bytes):
-  // WRITE: =>{{.*}}[[MEM_TAG]]
+  // WRITE: =>{{.*}}[[PTR_TAG]]{{[[:space:]]\[}}[[MEM_TAG]]
   // WRITE-NOT: recovered
 
   // READ: ERROR: HWAddressSanitizer: tag-mismatch on address
+  // READ-NOT: Invalid access starting at offset
   // READ: READ {{.*}} tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
   // READ: Memory tags around the buggy address (one tag corresponds to 16 bytes):
-  // READ: =>{{.*}}[[MEM_TAG]]
+  // READ: =>{{.*}}[[PTR_TAG]]{{[[:space:]]\[}}[[MEM_TAG]]
   // READ-NOT: recovered
 
   // RECOVER: recovered




More information about the llvm-commits mailing list