[compiler-rt] r190781 - [msan] Fix origin of deallocated memory.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Mon Sep 16 04:03:31 PDT 2013


Author: eugenis
Date: Mon Sep 16 06:03:31 2013
New Revision: 190781

URL: http://llvm.org/viewvc/llvm-project?rev=190781&view=rev
Log:
[msan] Fix origin of deallocated memory.

MSan poisons deallocated memory but it used to give it an invalid origin value,
resulting in confusing reports. This change associates deallocation stack trace
with such memory.

Note that MSan does not have quarantine, and use-after-free detection is very
limited.

Added:
    compiler-rt/trunk/lib/msan/lit_tests/use-after-free.cc   (with props)
Modified:
    compiler-rt/trunk/lib/msan/msan.cc
    compiler-rt/trunk/lib/msan/msan.h
    compiler-rt/trunk/lib/msan/msan_allocator.cc
    compiler-rt/trunk/lib/msan/msan_flags.h
    compiler-rt/trunk/lib/msan/msan_interceptors.cc
    compiler-rt/trunk/lib/msan/msan_new_delete.cc

Added: compiler-rt/trunk/lib/msan/lit_tests/use-after-free.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/lit_tests/use-after-free.cc?rev=190781&view=auto
==============================================================================
--- compiler-rt/trunk/lib/msan/lit_tests/use-after-free.cc (added)
+++ compiler-rt/trunk/lib/msan/lit_tests/use-after-free.cc Mon Sep 16 06:03:31 2013
@@ -0,0 +1,34 @@
+// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+// RUN: %clangxx_msan -m64 -O1 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+// RUN: %clangxx_msan -m64 -O2 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O0 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O1 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O2 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -m64 -O3 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out
+
+#include <stdlib.h>
+int main(int argc, char **argv) {
+  int *volatile p = (int *)malloc(sizeof(int));
+  *p = 42;
+  free(p);
+
+  if (*p)
+    exit(0);
+  // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
+  // CHECK: {{#0 0x.* in main .*use-after-free.cc:}}[[@LINE-3]]
+
+  // CHECK-ORIGINS: Uninitialized value was created by a heap allocation
+  // CHECK-ORIGINS: {{#0 0x.* in .*free}}
+  // CHECK-ORIGINS: {{#1 0x.* in main .*use-after-free.cc:}}[[@LINE-9]]
+  return 0;
+}

Propchange: compiler-rt/trunk/lib/msan/lit_tests/use-after-free.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: compiler-rt/trunk/lib/msan/msan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=190781&r1=190780&r2=190781&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.cc (original)
+++ compiler-rt/trunk/lib/msan/msan.cc Mon Sep 16 06:03:31 2013
@@ -122,6 +122,7 @@ static void ParseFlagsFromString(Flags *
   ParseFlag(str, &f->poison_heap_with_zeroes, "poison_heap_with_zeroes");
   ParseFlag(str, &f->poison_stack_with_zeroes, "poison_stack_with_zeroes");
   ParseFlag(str, &f->poison_in_malloc, "poison_in_malloc");
+  ParseFlag(str, &f->poison_in_malloc, "poison_in_free");
   ParseFlag(str, &f->exit_code, "exit_code");
   if (f->exit_code < 0 || f->exit_code > 127) {
     Printf("Exit code not in [0, 128) range: %d\n", f->exit_code);
@@ -153,6 +154,7 @@ static void InitializeFlags(Flags *f, co
   f->poison_heap_with_zeroes = false;
   f->poison_stack_with_zeroes = false;
   f->poison_in_malloc = true;
+  f->poison_in_free = true;
   f->exit_code = 77;
   f->report_umrs = true;
   f->verbosity = 0;

Modified: compiler-rt/trunk/lib/msan/msan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.h?rev=190781&r1=190780&r2=190781&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.h (original)
+++ compiler-rt/trunk/lib/msan/msan.h Mon Sep 16 06:03:31 2013
@@ -46,7 +46,7 @@ void InitializeInterceptors();
 
 void *MsanReallocate(StackTrace *stack, void *oldp, uptr size,
                      uptr alignment, bool zeroise);
-void MsanDeallocate(void *ptr);
+void MsanDeallocate(StackTrace *stack, void *ptr);
 void InstallTrapHandler();
 void InstallAtExitHandler();
 void ReplaceOperatorsNewAndDelete();

Modified: compiler-rt/trunk/lib/msan/msan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.cc?rev=190781&r1=190780&r2=190781&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_allocator.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_allocator.cc Mon Sep 16 06:03:31 2013
@@ -51,21 +51,23 @@ static void *MsanAllocate(StackTrace *st
   void *res = allocator.Allocate(&cache, size, alignment, false);
   Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(res));
   meta->requested_size = size;
-  if (zeroise)
+  if (zeroise) {
     __msan_clear_and_unpoison(res, size);
-  else if (flags()->poison_in_malloc)
+  } else if (flags()->poison_in_malloc) {
     __msan_poison(res, size);
-  if (__msan_get_track_origins()) {
-    u32 stack_id = StackDepotPut(stack->trace, stack->size);
-    CHECK(stack_id);
-    CHECK_EQ((stack_id >> 31), 0);  // Higher bit is occupied by stack origins.
-    __msan_set_origin(res, size, stack_id);
+    if (__msan_get_track_origins()) {
+      u32 stack_id = StackDepotPut(stack->trace, stack->size);
+      CHECK(stack_id);
+      CHECK_EQ((stack_id >> 31),
+               0);  // Higher bit is occupied by stack origins.
+      __msan_set_origin(res, size, stack_id);
+    }
   }
   MSAN_MALLOC_HOOK(res, size);
   return res;
 }
 
-void MsanDeallocate(void *p) {
+void MsanDeallocate(StackTrace *stack, void *p) {
   CHECK(p);
   Init();
   MSAN_FREE_HOOK(p);
@@ -74,9 +76,16 @@ void MsanDeallocate(void *p) {
   meta->requested_size = 0;
   // This memory will not be reused by anyone else, so we are free to keep it
   // poisoned.
-  __msan_poison(p, size);
-  if (__msan_get_track_origins())
-    __msan_set_origin(p, size, -1);
+  if (flags()->poison_in_free) {
+    __msan_poison(p, size);
+    if (__msan_get_track_origins()) {
+      u32 stack_id = StackDepotPut(stack->trace, stack->size);
+      CHECK(stack_id);
+      CHECK_EQ((stack_id >> 31),
+               0);  // Higher bit is occupied by stack origins.
+      __msan_set_origin(p, size, stack_id);
+    }
+  }
   allocator.Deallocate(&cache, p);
 }
 
@@ -85,7 +94,7 @@ void *MsanReallocate(StackTrace *stack,
   if (!old_p)
     return MsanAllocate(stack, new_size, alignment, zeroise);
   if (!new_size) {
-    MsanDeallocate(old_p);
+    MsanDeallocate(stack, old_p);
     return 0;
   }
   Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p));
@@ -103,7 +112,7 @@ void *MsanReallocate(StackTrace *stack,
   // Printf("realloc: old_size %zd new_size %zd\n", old_size, new_size);
   if (new_p)
     __msan_memcpy(new_p, old_p, memcpy_size);
-  MsanDeallocate(old_p);
+  MsanDeallocate(stack, old_p);
   return new_p;
 }
 

Modified: compiler-rt/trunk/lib/msan/msan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_flags.h?rev=190781&r1=190780&r2=190781&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_flags.h (original)
+++ compiler-rt/trunk/lib/msan/msan_flags.h Mon Sep 16 06:03:31 2013
@@ -23,6 +23,7 @@ struct Flags {
   bool poison_heap_with_zeroes;  // default: false
   bool poison_stack_with_zeroes;  // default: false
   bool poison_in_malloc;  // default: true
+  bool poison_in_free;  // default: true
   bool report_umrs;
   bool wrap_signals;
   bool halt_on_error;

Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=190781&r1=190780&r2=190781&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Mon Sep 16 06:03:31 2013
@@ -165,9 +165,9 @@ INTERCEPTOR(void *, pvalloc, SIZE_T size
 }
 
 INTERCEPTOR(void, free, void *ptr) {
-  ENSURE_MSAN_INITED();
+  GET_MALLOC_STACK_TRACE;
   if (ptr == 0) return;
-  MsanDeallocate(ptr);
+  MsanDeallocate(&stack, ptr);
 }
 
 INTERCEPTOR(SIZE_T, strlen, const char *s) {

Modified: compiler-rt/trunk/lib/msan/msan_new_delete.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_new_delete.cc?rev=190781&r1=190780&r2=190781&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_new_delete.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_new_delete.cc Mon Sep 16 06:03:31 2013
@@ -43,7 +43,8 @@ void *operator new(size_t size, std::not
 void *operator new[](size_t size, std::nothrow_t const&) { OPERATOR_NEW_BODY; }
 
 #define OPERATOR_DELETE_BODY \
-  if (ptr) MsanDeallocate(ptr)
+  GET_MALLOC_STACK_TRACE; \
+  if (ptr) MsanDeallocate(&stack, ptr)
 
 void operator delete(void *ptr) { OPERATOR_DELETE_BODY; }
 void operator delete[](void *ptr) { OPERATOR_DELETE_BODY; }





More information about the llvm-commits mailing list