[compiler-rt] r340591 - [hwasan] implement detection of double-free (invalid-free)

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 23 18:12:26 PDT 2018


Author: kcc
Date: Thu Aug 23 18:12:26 2018
New Revision: 340591

URL: http://llvm.org/viewvc/llvm-project?rev=340591&view=rev
Log:
[hwasan] implement detection of double-free (invalid-free)

Added:
    compiler-rt/trunk/test/hwasan/TestCases/double-free.c
Modified:
    compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc
    compiler-rt/trunk/lib/hwasan/hwasan_report.cc
    compiler-rt/trunk/lib/hwasan/hwasan_report.h

Modified: compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc?rev=340591&r1=340590&r2=340591&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc Thu Aug 23 18:12:26 2018
@@ -24,6 +24,7 @@
 #include "hwasan_mapping.h"
 #include "hwasan_thread.h"
 #include "hwasan_poisoning.h"
+#include "hwasan_report.h"
 
 namespace __hwasan {
 
@@ -173,11 +174,21 @@ static void *HwasanAllocate(StackTrace *
   return user_ptr;
 }
 
+static bool PointerAndMemoryTagsMatch(void *user_ptr) {
+  CHECK(user_ptr);
+  tag_t ptr_tag = GetTagFromPointer(reinterpret_cast<uptr>(user_ptr));
+  tag_t mem_tag = *reinterpret_cast<tag_t *>(
+      MEM_TO_SHADOW(GetAddressFromPointer(user_ptr)));
+  return ptr_tag == mem_tag;
+}
+
 void HwasanDeallocate(StackTrace *stack, void *user_ptr) {
   CHECK(user_ptr);
   HWASAN_FREE_HOOK(user_ptr);
 
   void *p = GetAddressFromPointer(user_ptr);
+  if (!PointerAndMemoryTagsMatch(user_ptr))
+    ReportInvalidFree(stack, reinterpret_cast<uptr>(user_ptr));
   Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(p));
   uptr size = meta->requested_size;
   meta->state = CHUNK_FREE;
@@ -226,7 +237,7 @@ void *HwasanReallocate(StackTrace *stack
           t ? t->GenerateRandomTag() : kFallbackAllocTag);
     }
     if (new_size > old_size) {
-      tag_t tag = GetTagFromPointer((uptr)user_old_p);
+      tag_t tag = GetTagFromPointer(reinterpret_cast<uptr>(user_old_p));
       TagMemoryAligned((uptr)old_p + old_size, new_size - old_size, tag);
     }
     return user_old_p;

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=340591&r1=340590&r2=340591&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_report.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_report.cc Thu Aug 23 18:12:26 2018
@@ -109,6 +109,54 @@ void ReportInvalidAccessInsideAddressRan
   //   DescribeMemoryRange(start, size);
 }
 
+static void PrintTagsAroundAddr(tag_t *tag_ptr) {
+  Printf(
+      "Memory tags around the buggy address (one tag corresponds to %zd "
+      "bytes):\n", kShadowAlignment);
+
+  const uptr row_len = 16;  // better be power of two.
+  const uptr num_rows = 11;
+  tag_t *center_row_beg = reinterpret_cast<tag_t *>(
+      RoundDownTo(reinterpret_cast<uptr>(tag_ptr), row_len));
+  tag_t *beg_row = center_row_beg - row_len * (num_rows / 2);
+  tag_t *end_row = center_row_beg + row_len * (num_rows / 2);
+  for (tag_t *row = beg_row; row < end_row; row += row_len) {
+    Printf("%s", row == center_row_beg ? "=>" : "  ");
+    for (uptr i = 0; i < row_len; i++) {
+      Printf("%s", row + i == tag_ptr ? "[" : " ");
+      Printf("%02x", row[i]);
+      Printf("%s", row + i == tag_ptr ? "]" : " ");
+    }
+    Printf("%s\n", row == center_row_beg ? "<=" : "  ");
+  }
+}
+
+void ReportInvalidFree(StackTrace *stack, uptr addr) {
+  ScopedErrorReportLock l;
+  uptr address = GetAddressFromPointer(addr);
+  tag_t ptr_tag = GetTagFromPointer(addr);
+  tag_t *tag_ptr = reinterpret_cast<tag_t*>(MEM_TO_SHADOW(address));
+  tag_t mem_tag = *tag_ptr;
+  Decorator d;
+  Printf("%s", d.Error());
+  uptr pc = stack->size ? stack->trace[0] : 0;
+  const char *bug_type = "invalid-free";
+  Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
+         address, pc);
+  Printf("%s", d.Access());
+  Printf("tags: %02x/%02x (ptr/mem)\n", ptr_tag, mem_tag);
+  Printf("%s", d.Default());
+
+  stack->Print();
+
+  PrintAddressDescription(address, 0);
+
+  PrintTagsAroundAddr(tag_ptr);
+
+  ReportErrorSummary(bug_type, stack);
+  Die();
+}
+
 void ReportTagMismatch(StackTrace *stack, uptr addr, uptr access_size,
                        bool is_store) {
   ScopedErrorReportLock l;
@@ -119,7 +167,8 @@ void ReportTagMismatch(StackTrace *stack
   // TODO: when possible, try to print heap-use-after-free, etc.
   const char *bug_type = "tag-mismatch";
   uptr pc = stack->size ? stack->trace[0] : 0;
-  Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type, address, pc);
+  Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
+         address, pc);
 
   tag_t ptr_tag = GetTagFromPointer(addr);
   tag_t *tag_ptr = reinterpret_cast<tag_t*>(MEM_TO_SHADOW(address));
@@ -133,25 +182,7 @@ void ReportTagMismatch(StackTrace *stack
 
   PrintAddressDescription(address, access_size);
 
-  Printf(
-      "Memory tags around the buggy address (one tag corresponds to %zd "
-      "bytes):\n", kShadowAlignment);
-
-  const uptr row_len = 16;  // better be power of two.
-  const uptr num_rows = 11;
-  tag_t *center_row_beg = reinterpret_cast<tag_t *>(
-      RoundDownTo(reinterpret_cast<uptr>(tag_ptr), row_len));
-  tag_t *beg_row = center_row_beg - row_len * (num_rows / 2);
-  tag_t *end_row = center_row_beg + row_len * (num_rows / 2);
-  for (tag_t *row = beg_row; row < end_row; row += row_len) {
-    Printf("%s", row == center_row_beg ? "=>" : "  ");
-    for (uptr i = 0; i < row_len; i++) {
-      Printf("%s", row + i == tag_ptr ? "[" : " ");
-      Printf("%02x", row[i]);
-      Printf("%s", row + i == tag_ptr ? "]" : " ");
-    }
-    Printf("%s\n", row == center_row_beg ? "<=" : "  ");
-  }
+  PrintTagsAroundAddr(tag_ptr);
 
   ReportErrorSummary(bug_type, stack);
 }

Modified: compiler-rt/trunk/lib/hwasan/hwasan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_report.h?rev=340591&r1=340590&r2=340591&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_report.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_report.h Thu Aug 23 18:12:26 2018
@@ -27,6 +27,7 @@ void ReportInvalidAccessInsideAddressRan
                                            uptr size, uptr offset);
 void ReportTagMismatch(StackTrace *stack, uptr addr, uptr access_size,
                        bool is_store);
+void ReportInvalidFree(StackTrace *stack, uptr addr);
 
 void ReportAtExitStatistics();
 

Added: compiler-rt/trunk/test/hwasan/TestCases/double-free.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/double-free.c?rev=340591&view=auto
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/double-free.c (added)
+++ compiler-rt/trunk/test/hwasan/TestCases/double-free.c Thu Aug 23 18:12:26 2018
@@ -0,0 +1,23 @@
+// RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// REQUIRES: stable-runtime
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sanitizer/hwasan_interface.h>
+
+int main() {
+  __hwasan_enable_allocator_tagging();
+  char * volatile x = (char*)malloc(40);
+  free(x);
+  free(x);
+// CHECK: ERROR: HWAddressSanitizer: invalid-free on address
+// CHECK: tags: [[PTR_TAG:..]]/[[MEM_TAG:..]] (ptr/mem)
+// CHECK: freed here:
+// CHECK: previously allocated here:
+// CHECK: Memory tags around the buggy address (one tag corresponds to 16 bytes):
+// CHECK: =>{{.*}}[[MEM_TAG]]
+  fprintf(stderr, "DONE\n");
+  __hwasan_disable_allocator_tagging();
+// CHECK-NOT: DONE
+}




More information about the llvm-commits mailing list