[compiler-rt] r179843 - [ASan] Make init-order checker allow access to already initialized globals.

Alexey Samsonov samsonov at google.com
Fri Apr 19 01:35:17 PDT 2013


Author: samsonov
Date: Fri Apr 19 03:35:16 2013
New Revision: 179843

URL: http://llvm.org/viewvc/llvm-project?rev=179843&view=rev
Log:
[ASan] Make init-order checker allow access to already initialized globals.

This change adds ASan runtime option "strict-init-order" (off by default)
that makes init-order checker bark if global initializer accesses any global from different
translation unit (even if the latter is already initialized). strict init-order checking
doesn't play well with, e.g. LLVM registration machineries, and causes issue 
https://code.google.com/p/address-sanitizer/issues/detail?id=178.

Added:
    compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc
    compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_flags.h
    compiler-rt/trunk/lib/asan/asan_globals.cc
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc

Modified: compiler-rt/trunk/lib/asan/asan_flags.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.h?rev=179843&r1=179842&r2=179843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.h (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.h Fri Apr 19 03:35:16 2013
@@ -113,6 +113,9 @@ struct Flags {
   // If true, assume that memcmp(p1, p2, n) always reads n bytes before
   // comparing p1 and p2.
   bool strict_memcmp;
+  // If true, assume that dynamic initializers can never access globals from
+  // other modules, even if the latter are already initialized.
+  bool strict_init_order;
 };
 
 extern Flags asan_flags_dont_use_directly;

Modified: compiler-rt/trunk/lib/asan/asan_globals.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_globals.cc?rev=179843&r1=179842&r2=179843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_globals.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_globals.cc Fri Apr 19 03:35:16 2013
@@ -37,7 +37,11 @@ static LowLevelAllocator allocator_for_g
 static ListOfGlobals *list_of_all_globals;
 
 static const int kDynamicInitGlobalsInitialCapacity = 512;
-typedef InternalVector<Global> VectorOfGlobals;
+struct DynInitGlobal {
+  Global g;
+  bool initialized;
+};
+typedef InternalVector<DynInitGlobal> VectorOfGlobals;
 // Lazy-initialized and never deleted.
 static VectorOfGlobals *dynamic_init_globals;
 
@@ -101,7 +105,8 @@ static void RegisterGlobal(const Global
       dynamic_init_globals = new(mem)
           VectorOfGlobals(kDynamicInitGlobalsInitialCapacity);
     }
-    dynamic_init_globals->push_back(*g);
+    DynInitGlobal dyn_global = { *g, false };
+    dynamic_init_globals->push_back(dyn_global);
   }
 }
 
@@ -150,6 +155,7 @@ void __asan_before_dynamic_init(const ch
   if (!flags()->check_initialization_order ||
       !flags()->poison_heap)
     return;
+  bool strict_init_order = flags()->strict_init_order;
   CHECK(dynamic_init_globals);
   CHECK(module_name);
   CHECK(asan_inited);
@@ -157,9 +163,14 @@ void __asan_before_dynamic_init(const ch
   if (flags()->report_globals >= 3)
     Printf("DynInitPoison module: %s\n", module_name);
   for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
-    const Global *g = &(*dynamic_init_globals)[i];
+    DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+    const Global *g = &dyn_g.g;
+    if (dyn_g.initialized)
+      continue;
     if (g->module_name != module_name)
       PoisonShadowForGlobal(g, kAsanInitializationOrderMagic);
+    else if (!strict_init_order)
+      dyn_g.initialized = true;
   }
 }
 
@@ -174,10 +185,13 @@ void __asan_after_dynamic_init() {
   BlockingMutexLock lock(&mu_for_globals);
   // FIXME: Optionally report that we're unpoisoning globals from a module.
   for (uptr i = 0, n = dynamic_init_globals->size(); i < n; ++i) {
-    const Global *g = &(*dynamic_init_globals)[i];
-    // Unpoison the whole global.
-    PoisonShadowForGlobal(g, 0);
-    // Poison redzones back.
-    PoisonRedZones(*g);
+    DynInitGlobal &dyn_g = (*dynamic_init_globals)[i];
+    const Global *g = &dyn_g.g;
+    if (!dyn_g.initialized) {
+      // Unpoison the whole global.
+      PoisonShadowForGlobal(g, 0);
+      // Poison redzones back.
+      PoisonRedZones(*g);
+    }
   }
 }

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=179843&r1=179842&r2=179843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Fri Apr 19 03:35:16 2013
@@ -125,6 +125,7 @@ static void ParseFlagsFromString(Flags *
   ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch");
   ParseFlag(str, &f->use_stack_depot, "use_stack_depot");
   ParseFlag(str, &f->strict_memcmp, "strict_memcmp");
+  ParseFlag(str, &f->strict_init_order, "strict_init_order");
 }
 
 static const char *asan_external_symbolizer;
@@ -170,6 +171,7 @@ void InitializeFlags(Flags *f, const cha
   f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0);;
   f->use_stack_depot = true;  // Only affects allocator2.
   f->strict_memcmp = true;
+  f->strict_init_order = false;
 
   // Override from compile definition.
   ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton());

Modified: compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc?rev=179843&r1=179842&r2=179843&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc (original)
+++ compiler-rt/trunk/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc Fri Apr 19 03:35:16 2013
@@ -1,12 +1,13 @@
 // Test to make sure basic initialization order errors are caught.
 // Check that on Linux initialization order bugs are caught
-// independently on order in which we list source files.
+// independently on order in which we list source files (if we specify
+// strict init-order checking).
 
 // RUN: %clangxx_asan -m64 -O0 %s %p/../Helpers/initialization-bug-extra.cc -o %t
-// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 \
+// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 \
 // RUN:    | %symbolize | FileCheck %s
 // RUN: %clangxx_asan -m64 -O0 %p/../Helpers/initialization-bug-extra.cc %s -o %t
-// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 \
+// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 \
 // RUN:    | %symbolize | FileCheck %s
 
 // Do not test with optimization -- the error may be optimized away.

Added: compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc?rev=179843&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc Fri Apr 19 03:35:16 2013
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <unistd.h>
+
+void inc_global();
+
+int slow_init() {
+  sleep(1);
+  inc_global();
+  return 42;
+}
+
+int slowly_init_glob = slow_init();

Added: compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc?rev=179843&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/init-order-dlopen.cc Fri Apr 19 03:35:16 2013
@@ -0,0 +1,47 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=178
+
+// RUN: %clangxx_asan -m64 -O0 %p/SharedLibs/init-order-dlopen-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m64 -O0 %s -o %t -Wl,--export-dynamic
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 | FileCheck %s
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#include <string>
+
+using std::string;
+
+int foo() {
+  return 42;
+}
+int global = foo();
+
+__attribute__((visibility("default")))
+void inc_global() {
+  global++;
+}
+
+void *global_poller(void *arg) {
+  while (true) {
+    if (global != 42)
+      break;
+    usleep(100);
+  }
+  return 0;
+}
+
+int main(int argc, char *argv[]) {
+  pthread_t p;
+  pthread_create(&p, 0, global_poller, 0);
+  string path = string(argv[0]) + "-so.so";
+  if (0 == dlopen(path.c_str(), RTLD_NOW)) {
+    fprintf(stderr, "dlerror: %s\n", dlerror());
+    return 1;
+  }
+  pthread_join(p, 0);
+  printf("PASSED\n");
+  // CHECK: PASSED
+  return 0;
+}





More information about the llvm-commits mailing list