[compiler-rt] r369825 - [GWP-ASan] Split options_parser and backtrace_sanitizer_common.

Mitch Phillips via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 23 16:23:48 PDT 2019


Author: hctim
Date: Fri Aug 23 16:23:48 2019
New Revision: 369825

URL: http://llvm.org/viewvc/llvm-project?rev=369825&view=rev
Log:
[GWP-ASan] Split options_parser and backtrace_sanitizer_common.

Summary:
optional/options_parser and optional/backtrace_sanitizer_common are logically
separate components. They both use sanitizer-common to power their
functionality, but there was an unstated implicit dependency that in order for
backtrace_sanitizer_common to function correctly, one had to also use
options_parser.

This was because options_parser called __sanitizer::InitialiseCommonFlags. This
is a requirement for backtrace_sanitizer_common to work, as the sanitizer
unwinder uses the sanitizer_common flags and will SEGV on a null page if
they're not initialised correctly.

This patch removes this hidden dependency. You can now use
backtrace_sanitizer_common without the requirements of options_parser.

This patch also makes the GWP-ASan unit tests only have a soft dependency on
sanitizer-common. The unit tests previously explicitly used
__sanitizer::Printf, which is now provided under
tests/optional/printf_sanitizer_common. This allows Android to build the unit
tests using their own signal-safe printf().

Reviewers: eugenis

Reviewed By: eugenis

Subscribers: srhines, mgorny, #sanitizers, llvm-commits, vlad.tsyrklevich, morehouse

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D66684

Added:
    compiler-rt/trunk/lib/gwp_asan/tests/optional/
    compiler-rt/trunk/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp
Modified:
    compiler-rt/trunk/lib/gwp_asan/optional/backtrace.h
    compiler-rt/trunk/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp
    compiler-rt/trunk/lib/gwp_asan/options.h
    compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt
    compiler-rt/trunk/lib/gwp_asan/tests/harness.h

Modified: compiler-rt/trunk/lib/gwp_asan/optional/backtrace.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/optional/backtrace.h?rev=369825&r1=369824&r2=369825&view=diff
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/optional/backtrace.h (original)
+++ compiler-rt/trunk/lib/gwp_asan/optional/backtrace.h Fri Aug 23 16:23:48 2019
@@ -17,7 +17,9 @@ namespace options {
 // and backtrace printing functions when RTGwpAsanBacktraceLibc or
 // RTGwpAsanBacktraceSanitizerCommon are linked. Use these functions to get the
 // backtrace function for populating the Options::Backtrace and
-// Options::PrintBacktrace when initialising the GuardedPoolAllocator.
+// Options::PrintBacktrace when initialising the GuardedPoolAllocator. Please
+// note any thread-safety descriptions for the implementation of these functions
+// that you use.
 Backtrace_t getBacktraceFunction();
 PrintBacktrace_t getPrintBacktraceFunction();
 } // namespace options

Modified: compiler-rt/trunk/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp?rev=369825&r1=369824&r2=369825&view=diff
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp (original)
+++ compiler-rt/trunk/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp Fri Aug 23 16:23:48 2019
@@ -13,6 +13,9 @@
 
 #include "gwp_asan/optional/backtrace.h"
 #include "gwp_asan/options.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_stacktrace.h"
 
 void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
@@ -58,7 +61,18 @@ static void PrintBacktrace(uintptr_t *Tr
 
 namespace gwp_asan {
 namespace options {
-Backtrace_t getBacktraceFunction() { return Backtrace; }
+// This function is thread-compatible. It must be synchronised in respect to any
+// other calls to getBacktraceFunction(), calls to getPrintBacktraceFunction(),
+// and calls to either of the functions that they return. Furthermore, this may
+// require synchronisation with any calls to sanitizer_common that use flags.
+// Generally, this function will be called during the initialisation of the
+// allocator, which is done in a thread-compatible manner.
+Backtrace_t getBacktraceFunction() {
+  // The unwinder requires the default flags to be set.
+  __sanitizer::SetCommonFlagsDefaults();
+  __sanitizer::InitializeCommonFlags();
+  return Backtrace;
+}
 PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
 } // namespace options
 } // namespace gwp_asan

Modified: compiler-rt/trunk/lib/gwp_asan/options.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/options.h?rev=369825&r1=369824&r2=369825&view=diff
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/options.h (original)
+++ compiler-rt/trunk/lib/gwp_asan/options.h Fri Aug 23 16:23:48 2019
@@ -25,6 +25,7 @@ namespace options {
 //   2. pointers: "%p"
 //   3. strings:  "%[-]([0-9]*)?(\\.\\*)?s"
 //   4. chars:    "%c"
+// This function must be implemented in a signal-safe manner.
 // =================================== Notes ===================================
 // This function has a slightly different signature than the C standard
 // library's printf(). Notably, it returns 'void' rather than 'int'.

Modified: compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt?rev=369825&r1=369824&r2=369825&view=diff
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/gwp_asan/tests/CMakeLists.txt Fri Aug 23 16:23:48 2019
@@ -8,7 +8,17 @@ set(GWP_ASAN_UNITTEST_CFLAGS
   -g)
 
 file(GLOB GWP_ASAN_HEADERS ../*.h)
-file(GLOB GWP_ASAN_UNITTESTS *.cpp)
+set(GWP_ASAN_UNITTESTS
+  optional/printf_sanitizer_common.cpp
+  alignment.cpp
+  backtrace.cpp
+  basic.cpp
+  compression.cpp
+  driver.cpp
+  mutex_test.cpp
+  slot_reuse.cpp
+  thread_contention.cpp)
+
 set(GWP_ASAN_UNIT_TEST_HEADERS
   ${GWP_ASAN_HEADERS}
   harness.h)
@@ -28,11 +38,9 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LI
 
   set(GWP_ASAN_TEST_RUNTIME RTGwpAsanTest.${arch})
 
-  # RTSanitizerCommonNoTermination(NoLibc) required for __sanitizer::Printf.
   set(GWP_ASAN_TEST_RUNTIME_OBJECTS
     $<TARGET_OBJECTS:RTGwpAsan.${arch}>
     $<TARGET_OBJECTS:RTGwpAsanBacktraceSanitizerCommon.${arch}>
-    $<TARGET_OBJECTS:RTGwpAsanOptionsParser.${arch}>
     $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
     $<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
     $<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>)

Modified: compiler-rt/trunk/lib/gwp_asan/tests/harness.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/tests/harness.h?rev=369825&r1=369824&r2=369825&view=diff
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/tests/harness.h (original)
+++ compiler-rt/trunk/lib/gwp_asan/tests/harness.h Fri Aug 23 16:23:48 2019
@@ -9,18 +9,24 @@
 #ifndef GWP_ASAN_TESTS_HARNESS_H_
 #define GWP_ASAN_TESTS_HARNESS_H_
 
-#include "gtest/gtest.h"
+#include <stdarg.h>
 
-// Include sanitizer_common first as gwp_asan/guarded_pool_allocator.h
-// transiently includes definitions.h, which overwrites some of the definitions
-// in sanitizer_common.
-#include "sanitizer_common/sanitizer_common.h"
+#include "gtest/gtest.h"
 
 #include "gwp_asan/guarded_pool_allocator.h"
 #include "gwp_asan/optional/backtrace.h"
-#include "gwp_asan/optional/options_parser.h"
 #include "gwp_asan/options.h"
 
+namespace gwp_asan {
+namespace test {
+// This printf-function getter allows other platforms (e.g. Android) to define
+// their own signal-safe Printf function. In LLVM, we use
+// `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf
+// for this purpose.
+options::Printf_t getPrintfFunction();
+}; // namespace test
+}; // namespace gwp_asan
+
 class DefaultGuardedPoolAllocator : public ::testing::Test {
 public:
   DefaultGuardedPoolAllocator() {
@@ -28,7 +34,7 @@ public:
     Opts.setDefaults();
     MaxSimultaneousAllocations = Opts.MaxSimultaneousAllocations;
 
-    Opts.Printf = __sanitizer::Printf;
+    Opts.Printf = gwp_asan::test::getPrintfFunction();
     GPA.init(Opts);
   }
 
@@ -49,7 +55,7 @@ public:
     Opts.MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg;
     MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg;
 
-    Opts.Printf = __sanitizer::Printf;
+    Opts.Printf = gwp_asan::test::getPrintfFunction();
     GPA.init(Opts);
   }
 
@@ -62,15 +68,10 @@ protected:
 class BacktraceGuardedPoolAllocator : public ::testing::Test {
 public:
   BacktraceGuardedPoolAllocator() {
-    // Call initOptions to initialise the internal sanitizer_common flags. These
-    // flags are referenced by the sanitizer_common unwinder, and if left
-    // uninitialised, they'll unintentionally crash the program.
-    gwp_asan::options::initOptions();
-
     gwp_asan::options::Options Opts;
     Opts.setDefaults();
 
-    Opts.Printf = __sanitizer::Printf;
+    Opts.Printf = gwp_asan::test::getPrintfFunction();
     Opts.Backtrace = gwp_asan::options::getBacktraceFunction();
     Opts.PrintBacktrace = gwp_asan::options::getPrintBacktraceFunction();
     GPA.init(Opts);

Added: compiler-rt/trunk/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp?rev=369825&view=auto
==============================================================================
--- compiler-rt/trunk/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp (added)
+++ compiler-rt/trunk/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp Fri Aug 23 16:23:48 2019
@@ -0,0 +1,22 @@
+//===-- printf_sanitizer_common.cpp -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "gwp_asan/options.h"
+
+namespace gwp_asan {
+namespace test {
+// This printf-function getter allows other platforms (e.g. Android) to define
+// their own signal-safe Printf function. In LLVM, we use
+// `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf
+// for this purpose.
+options::Printf_t getPrintfFunction() {
+  return __sanitizer::Printf;
+}
+}; // namespace test
+}; // namespace gwp_asan




More information about the llvm-commits mailing list