[compiler-rt] r216692 - [asan] introduce __asan_load_cxx_array_cookie: check that the array cookie address is properly poisoned and return the cookie value. If not, return 0 to avoid infinite loop of DTORs (in case of use-after-free). Calls to this function will be inserted by clang (separate change)

Kostya Serebryany kcc at google.com
Thu Aug 28 15:28:04 PDT 2014


Author: kcc
Date: Thu Aug 28 17:28:04 2014
New Revision: 216692

URL: http://llvm.org/viewvc/llvm-project?rev=216692&view=rev
Log:
[asan] introduce __asan_load_cxx_array_cookie: check that the array cookie address is properly poisoned and return the cookie value. If not, return 0 to avoid infinite loop of DTORs (in case of use-after-free). Calls to this function will be inserted by clang (separate change)

Added:
    compiler-rt/trunk/test/asan/TestCases/Linux/new_array_cookie_uaf_test.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_interface_internal.h
    compiler-rt/trunk/lib/asan/asan_poisoning.cc

Modified: compiler-rt/trunk/lib/asan/asan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interface_internal.h?rev=216692&r1=216691&r2=216692&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interface_internal.h Thu Aug 28 17:28:04 2014
@@ -149,6 +149,8 @@ extern "C" {
 
   SANITIZER_INTERFACE_ATTRIBUTE
   void __asan_poison_cxx_array_cookie(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE
+  uptr __asan_load_cxx_array_cookie(uptr *p);
 }  // extern "C"
 
 #endif  // ASAN_INTERFACE_INTERNAL_H

Modified: compiler-rt/trunk/lib/asan/asan_poisoning.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_poisoning.cc?rev=216692&r1=216691&r2=216692&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_poisoning.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_poisoning.cc Thu Aug 28 17:28:04 2014
@@ -232,7 +232,24 @@ void __asan_poison_cxx_array_cookie(uptr
   if (SANITIZER_WORDSIZE != 64) return;
   if (!flags()->poison_array_cookie) return;
   uptr s = MEM_TO_SHADOW(p);
-  *reinterpret_cast<u8*>(s) = 0xac;
+  *reinterpret_cast<u8*>(s) = kAsanArrayCookieMagic;
+}
+
+extern "C" SANITIZER_INTERFACE_ATTRIBUTE
+uptr __asan_load_cxx_array_cookie(uptr *p) {
+  if (SANITIZER_WORDSIZE != 64) return *p;
+  if (!flags()->poison_array_cookie) return *p;
+  uptr s = MEM_TO_SHADOW(reinterpret_cast<uptr>(p));
+  u8 sval = *reinterpret_cast<u8*>(s);
+  if (sval == kAsanArrayCookieMagic) return *p;
+  // If sval is not kAsanArrayCookieMagic it can only be freed memory,
+  // which means that we are going to get double-free. So, return 0 to avoid
+  // infinite loop of destructors. We don't want to report a double-free here
+  // though, so print a warning just in case.
+  CHECK_EQ(sval, kAsanHeapFreeMagic);
+  Report("AddressSanitizer: loaded array cookie from free-d memory; "
+         "expect a double-free report\n");
+  return 0;
 }
 
 // This is a simplified version of __asan_(un)poison_memory_region, which

Added: compiler-rt/trunk/test/asan/TestCases/Linux/new_array_cookie_uaf_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/new_array_cookie_uaf_test.cc?rev=216692&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/new_array_cookie_uaf_test.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/new_array_cookie_uaf_test.cc Thu Aug 28 17:28:04 2014
@@ -0,0 +1,28 @@
+// REQUIRES: asan-64-bits
+// RUN: %clangxx_asan -O3 %s -o %t
+// DISABLED: ASAN_OPTIONS=poison_array_cookie=1 not %run %t 2>&1  | FileCheck %s --check-prefix=COOKIE
+// RUN: ASAN_OPTIONS=poison_array_cookie=0 not %run %t 2>&1  | FileCheck %s --check-prefix=NO_COOKIE
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+int dtor_counter;
+struct C {
+  int x;
+  ~C() {
+    fprintf(stderr, "DTOR\n");
+    dtor_counter++;
+    if (dtor_counter >= 100) {
+      fprintf(stderr, "Called DTOR too many times\n");
+// NO_COOKIE: Called DTOR too many times
+      exit(1);
+    }
+  }
+};
+
+int main(int argc, char **argv) {
+  C *buffer = new C[argc];
+  delete [] buffer;
+  delete [] buffer;
+// COOKIE: AddressSanitizer: loaded array cookie from free-d memory
+// COOKIE: AddressSanitizer: attempting double-free
+}





More information about the llvm-commits mailing list