[compiler-rt] r208760 - [asan] Respect personality in kernel area detector, patch by Yuri Gribov

Kostya Serebryany kcc at google.com
Wed May 14 01:13:11 PDT 2014


Author: kcc
Date: Wed May 14 03:13:11 2014
New Revision: 208760

URL: http://llvm.org/viewvc/llvm-project?rev=208760&view=rev
Log:
[asan] Respect personality in kernel area detector, patch by Yuri Gribov

Modified:
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
    compiler-rt/trunk/test/asan/TestCases/Linux/kernel-area.cc

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=208760&r1=208759&r2=208760&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Wed May 14 03:13:11 2014
@@ -556,6 +556,12 @@ static void AsanInitInternal() {
   SanitizerToolName = "AddressSanitizer";
   CHECK(!asan_init_is_running && "ASan init calls itself!");
   asan_init_is_running = true;
+
+  // Initialize flags. This must be done early, because most of the
+  // initialization steps look at flags().
+  const char *options = GetEnv("ASAN_OPTIONS");
+  InitializeFlags(flags(), options);
+
   InitializeHighMemEnd();
 
   // Make sure we are not statically linked.
@@ -566,11 +572,6 @@ static void AsanInitInternal() {
   SetCheckFailedCallback(AsanCheckFailed);
   SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
 
-  // Initialize flags. This must be done early, because most of the
-  // initialization steps look at flags().
-  const char *options = GetEnv("ASAN_OPTIONS");
-  InitializeFlags(flags(), options);
-
   if (!flags()->start_deactivated)
     ParseExtraActivationFlags();
 

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc?rev=208760&r1=208759&r2=208760&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.cc Wed May 14 03:13:11 2014
@@ -55,6 +55,7 @@ void SetCommonFlagsDefaults(CommonFlags
   f->legacy_pthread_cond = false;
   f->intercept_tls_get_addr = false;
   f->coverage = false;
+  f->full_address_space = false;
 }
 
 void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
@@ -126,6 +127,9 @@ void ParseCommonFlagsFromString(CommonFl
   ParseFlag(str, &f->coverage, "coverage",
       "If set, coverage information will be dumped at program shutdown (if the "
       "coverage instrumentation was enabled at compile time).");
+  ParseFlag(str, &f->full_address_space, "full_address_space",
+            "Sanitize complete address space; "
+            "by default kernel area on 32-bit platforms will not be sanitized");
 
   // Do a sanity check for certain flags.
   if (f->malloc_context_size < 1)

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h?rev=208760&r1=208759&r2=208760&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.h Wed May 14 03:13:11 2014
@@ -54,6 +54,7 @@ struct CommonFlags {
   bool help;
   uptr mmap_limit_mb;
   bool coverage;
+  bool full_address_space;
 };
 
 inline CommonFlags *common_flags() {

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc?rev=208760&r1=208759&r2=208760&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc Wed May 14 03:13:11 2014
@@ -24,6 +24,7 @@
 
 #if SANITIZER_LINUX
 #include <sys/utsname.h>
+#include <sys/personality.h>
 #endif
 
 namespace __sanitizer {
@@ -34,16 +35,36 @@ uptr GetMmapGranularity() {
 }
 
 #if SANITIZER_WORDSIZE == 32
-// Take care of unusable kernel area in top gigabyte
-static uptr GetKernelStartAddress() {
-#if 0  // SANITIZER_LINUX
-  // FIXME: this code is too naive. We have a situation where the machine is a
-  // true x8_64, but under schroot uname returns i686.
-  // 64-bit Linux provides 32-bit apps with full address space
+// Take care of unusable kernel area in top gigabyte.
+static uptr GetKernelAreaSize() {
+#if SANITIZER_LINUX
+  const uptr gbyte = 1UL << 30;
+
+  // Firstly check if there are writable segments
+  // mapped to top gigabyte (e.g. stack).
+  MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+  uptr end, prot;
+  while (proc_maps.Next(/*start*/0, &end,
+                        /*offset*/0, /*filename*/0,
+                        /*filename_size*/0, &prot)) {
+    if ((end >= 3 * gbyte)
+        && (prot & MemoryMappingLayout::kProtectionWrite) != 0)
+      return 0;
+  }
+
+  // Even if nothing is mapped, top Gb may still be accessible
+  // if we are running on 64-bit kernel.
+  // Uname may report misleading results if personality type
+  // is modified (e.g. under schroot) so check this as well.
   struct utsname uname_info;
-  return 0 == uname(&uname_info) && !internal_strstr(uname_info.machine, "64")
-    ? 1ULL << 30
-    : 0;
+  int pers = personality(0xffffffffUL);
+  if (!(pers & PER_MASK)
+      && uname(&uname_info) == 0
+      && internal_strstr(uname_info.machine, "64"))
+    return 0;
+
+  // Top gigabyte is reserved for kernel.
+  return gbyte;
 #else
   return 0;
 #endif  // SANITIZER_LINUX
@@ -66,7 +87,8 @@ uptr GetMaxVirtualAddress() {
 # endif
 #else  // SANITIZER_WORDSIZE == 32
   uptr res = (1ULL << 32) - 1;  // 0xffffffff;
-  res -= GetKernelStartAddress();
+  if (!common_flags()->full_address_space)
+    res -= GetKernelAreaSize();
   CHECK_LT(reinterpret_cast<uptr>(&res), res);
   return res;
 #endif  // SANITIZER_WORDSIZE

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/kernel-area.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/kernel-area.cc?rev=208760&r1=208759&r2=208760&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/kernel-area.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/kernel-area.cc Wed May 14 03:13:11 2014
@@ -2,6 +2,8 @@
 //
 // RUN: %clangxx_asan %s -o %t
 // RUN: ASAN_OPTIONS=verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%kernel_bits
+// RUN: ASAN_OPTIONS=verbosity=1:full_address_space=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%kernel_bits
+// RUN: ASAN_OPTIONS=verbosity=1:full_address_space=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-kernel-64-bits
 //
 // CHECK-kernel-32-bits: || `[0x38000000, 0xbfffffff]` || HighMem    ||
 // CHECK-kernel-32-bits: || `[0x27000000, 0x37ffffff]` || HighShadow ||





More information about the llvm-commits mailing list