[compiler-rt] r267747 - [sanitizer] [SystemZ] Abort if the kernel might be vulnerable to CVE-2016-2143.

Marcin Koscielnicki via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 27 10:42:00 PDT 2016


Author: koriakin
Date: Wed Apr 27 12:42:00 2016
New Revision: 267747

URL: http://llvm.org/viewvc/llvm-project?rev=267747&view=rev
Log:
[sanitizer] [SystemZ] Abort if the kernel might be vulnerable to CVE-2016-2143.

In short, CVE-2016-2143 will crash the machine if a process uses both >4TB
virtual addresses and fork().  ASan, TSan, and MSan will, by necessity, map
a sizable chunk of virtual address space, which is much larger than 4TB.
Even worse, sanitizers will always use fork() for llvm-symbolizer when a bug
is detected.  Disable all three by aborting on process initialization if
the running kernel version is not known to contain a fix.

Unfortunately, there's no reliable way to detect the fix without crashing
the kernel.  So, we rely on whitelisting - I've included a list of upstream
kernel versions that will work.  In case someone uses a distribution kernel
or applied the fix themselves, an override switch is also included.

Differential Revision: http://reviews.llvm.org/D19576

Modified:
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/lib/dfsan/dfsan.cc
    compiler-rt/trunk/lib/lsan/lsan.cc
    compiler-rt/trunk/lib/msan/msan.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_s390.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.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=267747&r1=267746&r2=267747&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Wed Apr 27 12:42:00 2016
@@ -415,6 +415,7 @@ static void AsanInitInternal() {
 
   AsanCheckIncompatibleRT();
   AsanCheckDynamicRTPrereqs();
+  AvoidCVE_2016_2143();
 
   SetCanPoisonMemory(flags()->poison_heap);
   SetMallocContextSize(common_flags()->malloc_context_size);

Modified: compiler-rt/trunk/lib/dfsan/dfsan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/dfsan/dfsan.cc?rev=267747&r1=267746&r2=267747&view=diff
==============================================================================
--- compiler-rt/trunk/lib/dfsan/dfsan.cc (original)
+++ compiler-rt/trunk/lib/dfsan/dfsan.cc Wed Apr 27 12:42:00 2016
@@ -368,6 +368,7 @@ static void InitializeFlags() {
 }
 
 static void InitializePlatformEarly() {
+  AvoidCVE_2016_2143();
 #ifdef DFSAN_RUNTIME_VMA
   __dfsan::vmaSize =
     (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);

Modified: compiler-rt/trunk/lib/lsan/lsan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan.cc?rev=267747&r1=267746&r2=267747&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan.cc Wed Apr 27 12:42:00 2016
@@ -72,6 +72,7 @@ extern "C" void __lsan_init() {
   lsan_init_is_running = true;
   SanitizerToolName = "LeakSanitizer";
   CacheBinaryName();
+  AvoidCVE_2016_2143();
   InitializeFlags();
   InitCommonLsan();
   InitializeAllocator();

Modified: compiler-rt/trunk/lib/msan/msan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=267747&r1=267746&r2=267747&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.cc (original)
+++ compiler-rt/trunk/lib/msan/msan.cc Wed Apr 27 12:42:00 2016
@@ -375,6 +375,7 @@ void __msan_init() {
   msan_init_is_running = 1;
   SanitizerToolName = "MemorySanitizer";
 
+  AvoidCVE_2016_2143();
   InitTlsSize();
 
   CacheBinaryName();

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=267747&r1=267746&r2=267747&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Wed Apr 27 12:42:00 2016
@@ -809,6 +809,16 @@ RunOnDestruction<Fn> at_scope_exit(Fn fn
   return RunOnDestruction<Fn>(fn);
 }
 
+// Linux on 64-bit s390 had a nasty bug that crashes the whole machine
+// if a process uses virtual memory over 4TB (as many sanitizers like
+// to do).  This function will abort the process if running on a kernel
+// that looks vulnerable.
+#if SANITIZER_LINUX && SANITIZER_S390_64
+void AvoidCVE_2016_2143();
+#else
+INLINE void AvoidCVE_2016_2143() {}
+#endif
+
 }  // namespace __sanitizer
 
 inline void *operator new(__sanitizer::operator_new_size_type size,

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_s390.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_s390.cc?rev=267747&r1=267746&r2=267747&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_s390.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_s390.cc Wed Apr 27 12:42:00 2016
@@ -16,10 +16,12 @@
 
 #if SANITIZER_LINUX && SANITIZER_S390
 
+#include "sanitizer_libc.h"
 #include "sanitizer_linux.h"
 
 #include <errno.h>
 #include <sys/syscall.h>
+#include <sys/utsname.h>
 #include <unistd.h>
 
 namespace __sanitizer {
@@ -114,6 +116,73 @@ uptr internal_clone(int (*fn)(void *), v
   return res;
 }
 
+#if SANITIZER_S390_64
+static bool FixedCVE_2016_2143() {
+  // Try to determine if the running kernel has a fix for CVE-2016-2143,
+  // return false if in doubt (better safe than sorry).  Distros may want to
+  // adjust this for their own kernels.
+  struct utsname buf;
+  unsigned int major, minor, patch = 0;
+  // This should never fail, but just in case...
+  if (uname(&buf))
+    return false;
+  char *ptr = buf.release;
+  major = internal_simple_strtoll(ptr, &ptr, 10);
+  // At least first 2 should be matched.
+  if (ptr[0] != '.')
+    return false;
+  minor = internal_simple_strtoll(ptr+1, &ptr, 10);
+  // Third is optional.
+  if (ptr[0] == '.')
+    patch = internal_simple_strtoll(ptr+1, &ptr, 10);
+  if (major < 3) {
+    // <3.0 is bad.
+    return false;
+  } else if (major == 3) {
+    // 3.2.79+ is OK.
+    if (minor == 2 && patch >= 79)
+      return true;
+    // Otherwise, bad.
+    return false;
+  } else if (major == 4) {
+    // 4.1.21+ is OK.
+    if (minor == 1 && patch >= 21)
+      return true;
+    // 4.4.6+ is OK.
+    if (minor == 4 && patch >= 6)
+      return true;
+    // Otherwise, OK if 4.5+.
+    return minor >= 5;
+  } else {
+    // Linux 5 and up are fine.
+    return true;
+  }
+}
+
+void AvoidCVE_2016_2143() {
+  // Older kernels are affected by CVE-2016-2143 - they will crash hard
+  // if someone uses 4-level page tables (ie. virtual addresses >= 4TB)
+  // and fork() in the same process.  Unfortunately, sanitizers tend to
+  // require such addresses.  Since this is very likely to crash the whole
+  // machine (sanitizers themselves use fork() for llvm-symbolizer, for one),
+  // abort the process at initialization instead.
+  if (FixedCVE_2016_2143())
+    return;
+  if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))
+    return;
+  Report(
+    "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143.  Using ASan,\n"
+    "MSan, TSan, DFSan or LSan with such kernel can and will crash your\n"
+    "machine, or worse.\n"
+    "\n"
+    "If you are certain your kernel is not vulnerable (you have compiled it\n"
+    "yourself, or are using an unrecognized distribution kernel), you can\n"
+    "override this safety check by exporting SANITIZER_IGNORE_CVE_2016_2143\n"
+    "with any value.\n");
+  Die();
+}
+#endif
+
 } // namespace __sanitizer
 
 #endif // SANITIZER_LINUX && SANITIZER_S390

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc?rev=267747&r1=267746&r2=267747&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.cc Wed Apr 27 12:42:00 2016
@@ -321,6 +321,7 @@ void Initialize(ThreadState *thr) {
   const char *options = GetEnv(kTsanOptionsEnv);
   CacheBinaryName();
   InitializeFlags(&ctx->flags, options);
+  AvoidCVE_2016_2143();
   InitializePlatformEarly();
 #ifndef SANITIZER_GO
   // Re-exec ourselves if we need to set additional env or command line args.




More information about the llvm-commits mailing list