Hi,
  These two patches are what I use to fix testing of the santizers
with qemu.  The first one disables coloring always as for some reason
when running with qemu (but not normally), coloring is detected.  I
have not gone and debugged the reason why the sanitizers does not
detect coloring when run under dejagnu even though, it is designed to
be running under a psedu-TTY.

The second patch disables LSAN when clone with the arguments that are
needed to stop the world fail.  This second patch should in theory go
upstream but I am not going to that right now; plus maybe it should
only disable it when used with asan instead of in general.

With these two patches, I get clean test results on aarch64-linux-gnu.
I am mainly sending them here as I think they are useful for people
who are doing testing; especially cross testing.

Thanks,
Andrew Pinski
From 7666c4ec5db5e99530f8ff9411b782326ce96655 Mon Sep 17 00:00:00 2001
From: Andrew Pinski <apin...@marvell.com>
Date: Thu, 6 Feb 2020 02:06:27 +0000
Subject: [PATCH 1/2] Set default coloring to never.

Auto does not work always.  So just disable coloring.

Change-Id: I68564c6b4c35ed6d7f4e2938d765f428995900e7
Signed-off-by: Andrew Pinski <apin...@marvell.com>
---
 libsanitizer/sanitizer_common/sanitizer_flags.inc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.inc 
b/libsanitizer/sanitizer_common/sanitizer_flags.inc
index 065258a5a6e..9caf442b2d1 100644
--- a/libsanitizer/sanitizer_common/sanitizer_flags.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_flags.inc
@@ -108,7 +108,7 @@ COMMON_FLAG(
     uptr, clear_shadow_mmap_threshold, 64 * 1024,
     "Large shadow regions are zero-filled using mmap(NORESERVE) instead of "
     "memset(). This is the threshold size in bytes.")
-COMMON_FLAG(const char *, color, "auto",
+COMMON_FLAG(const char *, color, "never",
             "Colorize reports: (always|never|auto).")
 COMMON_FLAG(
     bool, legacy_pthread_cond, false,
-- 
2.17.1

From 1a931d339e6e89bdc7292f6c52ba5f89278bda6a Mon Sep 17 00:00:00 2001
From: Andrew Pinski <apin...@marvell.com>
Date: Thu, 6 Feb 2020 17:18:26 -0800
Subject: [PATCH 2/2] Have the ability to disable lsan if clone fails.

clone fails for some cases for qemu, lsan is not needed
for asan testing.  So we can get lsan disabled when the
clone fails.

Tested on aarch64-linux-gnu with qemu.  All asan.exp tests now pass.

Change-Id: I1e281a3701ef0a1a4325ce2fbf8ca263a930fbe5
Signed-off-by: Andrew Pinski <apin...@marvell.com>
---
 libsanitizer/asan/asan_rtl.cpp    |  2 +-
 libsanitizer/lsan/lsan.cpp        |  5 ++
 libsanitizer/lsan/lsan_common.cpp | 81 +++++++++++++++++++++++++++++++
 libsanitizer/lsan/lsan_common.h   |  1 +
 4 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/libsanitizer/asan/asan_rtl.cpp b/libsanitizer/asan/asan_rtl.cpp
index 594d7752eea..93ef79e111d 100644
--- a/libsanitizer/asan/asan_rtl.cpp
+++ b/libsanitizer/asan/asan_rtl.cpp
@@ -500,7 +500,7 @@ static void AsanInitInternal() {
 
   if (CAN_SANITIZE_LEAKS) {
     __lsan::InitCommonLsan();
-    if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
+    if (!__lsan::lsan_cannotwork && common_flags()->detect_leaks && 
common_flags()->leak_check_at_exit) {
       if (flags()->halt_on_error)
         Atexit(__lsan::DoLeakCheck);
       else
diff --git a/libsanitizer/lsan/lsan.cpp b/libsanitizer/lsan/lsan.cpp
index 4ce03046ffb..3488f0436a1 100644
--- a/libsanitizer/lsan/lsan.cpp
+++ b/libsanitizer/lsan/lsan.cpp
@@ -108,6 +108,11 @@ extern "C" void __lsan_init() {
   AvoidCVE_2016_2143();
   InitializeFlags();
   InitCommonLsan();
+  if (lsan_cannotwork) {
+    lsan_init_is_running = false;
+    lsan_inited = true;
+    return;
+  }
   InitializeAllocator();
   ReplaceSystemMalloc();
   InitTlsSize();
diff --git a/libsanitizer/lsan/lsan_common.cpp 
b/libsanitizer/lsan/lsan_common.cpp
index 9ff9f4c5d1c..2023a9685dd 100644
--- a/libsanitizer/lsan/lsan_common.cpp
+++ b/libsanitizer/lsan/lsan_common.cpp
@@ -25,9 +25,17 @@
 #include "sanitizer_common/sanitizer_thread_registry.h"
 #include "sanitizer_common/sanitizer_tls_get_addr.h"
 
+#if SANITIZER_LINUX
+#include <sched.h> // for CLONE_* definitions
+#include <sys/wait.h> // for signal-related stuff
+#include <errno.h>
+#endif
+
 #if CAN_SANITIZE_LEAKS
 namespace __lsan {
 
+bool lsan_cannotwork;
+
 // This mutex is used to prevent races between DoLeakCheck and IgnoreObject, 
and
 // also to protect the global list of root regions.
 BlockingMutex global_mutex(LINKER_INITIALIZED);
@@ -111,7 +119,76 @@ const char *MaybeCallLsanDefaultOptions() {
   return (&__lsan_default_options) ? __lsan_default_options() : "";
 }
 
+#if SANITIZER_LINUX
+namespace {
+
+class ScopedStackSpaceWithGuard {
+ public:
+  explicit ScopedStackSpaceWithGuard(uptr stack_size) {
+    stack_size_ = stack_size;
+    guard_size_ = GetPageSizeCached();
+    // FIXME: Omitting MAP_STACK here works in current kernels but might break
+    // in the future.
+    guard_start_ = (uptr)MmapOrDie(stack_size_ + guard_size_,
+                                   "ScopedStackWithGuard");
+    CHECK(MprotectNoAccess((uptr)guard_start_, guard_size_));
+  }
+  ~ScopedStackSpaceWithGuard() {
+    UnmapOrDie((void *)guard_start_, stack_size_ + guard_size_);
+  }
+  void *Bottom() const {
+    return (void *)(guard_start_ + stack_size_ + guard_size_);
+  }
+
+ private:
+  uptr stack_size_;
+  uptr guard_size_;
+  uptr guard_start_;
+};
+}
+
+static int lsan_tester(void* argument) {
+  return 0;
+}
+#endif
+
+static bool can_lsan_run() {
+#if SANITIZER_LINUX
+  // The required stack size to return 0 is small, just use 64k as it is the
+  // largest known page size
+  const uptr kTempStackSize = 4 * 1024 * 1024;
+  int local_errno = 0;
+  VReport(1, "spawning a tracer thread .\n");
+  ScopedStackSpaceWithGuard temp_stack(kTempStackSize);
+  uptr tracer_pid = internal_clone(
+      lsan_tester, temp_stack.Bottom(),
+      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,
+      nullptr, nullptr /* parent_tidptr */,
+      nullptr /* newtls */, nullptr /* child_tidptr */);
+  if (internal_iserror(tracer_pid, &local_errno)) {
+    VReport(1, "Failed spawning a tracer thread (errno %d).\n", local_errno);
+    return false;
+  }
+    for (;;) {
+      uptr waitpid_status = internal_waitpid(tracer_pid, nullptr, __WALL);
+      if (!internal_iserror(waitpid_status, &local_errno))
+        break;
+      if (local_errno == EINTR)
+        continue;
+      VReport(1, "Waiting on the tracer thread failed (errno %d).\n",
+              local_errno);
+      break;
+    }
+
+#endif
+  return true;
+}
+
 void InitCommonLsan() {
+  if (!can_lsan_run ()) {
+    lsan_cannotwork = true;
+    return;
+  }
   InitializeRootRegions();
   if (common_flags()->detect_leaks) {
     // Initialization which can fail or print warnings should only be done if
@@ -565,6 +642,8 @@ static void CheckForLeaksCallback(const 
SuspendedThreadsList &suspended_threads,
 }
 
 static bool CheckForLeaks() {
+  if (lsan_cannotwork)
+      return false;
   if (&__lsan_is_turned_off && __lsan_is_turned_off())
       return false;
   EnsureMainThreadIDIsCorrect();
@@ -606,6 +685,7 @@ static bool has_reported_leaks = false;
 bool HasReportedLeaks() { return has_reported_leaks; }
 
 void DoLeakCheck() {
+  if (lsan_cannotwork) return;
   BlockingMutexLock l(&global_mutex);
   static bool already_done;
   if (already_done) return;
@@ -615,6 +695,7 @@ void DoLeakCheck() {
 }
 
 static int DoRecoverableLeakCheck() {
+  if (lsan_cannotwork) return 0;
   BlockingMutexLock l(&global_mutex);
   bool have_leaks = CheckForLeaks();
   return have_leaks ? 1 : 0;
diff --git a/libsanitizer/lsan/lsan_common.h b/libsanitizer/lsan/lsan_common.h
index d24abe31b71..8b683af7652 100644
--- a/libsanitizer/lsan/lsan_common.h
+++ b/libsanitizer/lsan/lsan_common.h
@@ -53,6 +53,7 @@ struct DTLS;
 }
 
 namespace __lsan {
+extern bool lsan_cannotwork;
 
 // Chunk tags.
 enum ChunkTag {
-- 
2.17.1

Reply via email to