<div dir="ltr">I am sorry that I couldn't review this patch in time (I was OOO) but I very much dislike it. <div>Please revert and then let's do a proper patch. </div><div>See my recent comments in the review tool. </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Apr 14, 2016 at 5:56 AM, Marcin Koscielnicki via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: koriakin<br>
Date: Thu Apr 14 07:56:24 2016<br>
New Revision: 266297<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=266297&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=266297&view=rev</a><br>
Log:<br>
[sanitizer] [SystemZ] Abort if the kernel might be vulnerable to CVE-2016-2143.<br>
<br>
In short, CVE-2016-2143 will crash the machine if a process uses both >4TB<br>
virtual addresses and fork().  ASan, TSan, and MSan will, by necessity, map<br>
a sizable chunk of virtual address space, which is much larger than 4TB.<br>
Even worse, sanitizers will always use fork() for llvm-symbolizer when a bug<br>
is detected.  Disable all three by aborting on process initialization if<br>
the running kernel version is not known to contain a fix.<br>
<br>
Unfortunately, there's no reliable way to detect the fix without crashing<br>
the kernel.  So, we rely on whitelisting - I've included a list of upstream<br>
kernel versions that will work.  In case someone uses a distribution kernel<br>
or applied the fix themselves, an override switch is also included.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D18915" rel="noreferrer" target="_blank">http://reviews.llvm.org/D18915</a><br>
<br>
Modified:<br>
    compiler-rt/trunk/lib/asan/asan_rtl.cc<br>
    compiler-rt/trunk/lib/msan/msan.cc<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc<br>
<br>
Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=266297&r1=266296&r2=266297&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=266297&r1=266296&r2=266297&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)<br>
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Thu Apr 14 07:56:24 2016<br>
@@ -27,6 +27,10 @@<br>
 #include "sanitizer_common/sanitizer_atomic.h"<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
 #include "sanitizer_common/sanitizer_libc.h"<br>
+#if defined(__s390x__) && defined(__linux__)<br>
+// For AvoidCVE_2016_2143.<br>
+#include "sanitizer_common/sanitizer_linux.h"<br>
+#endif<br>
 #include "sanitizer_common/sanitizer_symbolizer.h"<br>
 #include "lsan/lsan_common.h"<br>
 #include "ubsan/ubsan_init.h"<br>
@@ -415,6 +419,9 @@ static void AsanInitInternal() {<br>
<br>
   AsanCheckIncompatibleRT();<br>
   AsanCheckDynamicRTPrereqs();<br>
+#if defined(__s390x__) && defined(__linux__)<br>
+  AvoidCVE_2016_2143();<br>
+#endif<br>
<br>
   SetCanPoisonMemory(flags()->poison_heap);<br>
   SetMallocContextSize(common_flags()->malloc_context_size);<br>
<br>
Modified: compiler-rt/trunk/lib/msan/msan.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=266297&r1=266296&r2=266297&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=266297&r1=266296&r2=266297&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/msan/msan.cc (original)<br>
+++ compiler-rt/trunk/lib/msan/msan.cc Thu Apr 14 07:56:24 2016<br>
@@ -22,6 +22,10 @@<br>
 #include "sanitizer_common/sanitizer_flags.h"<br>
 #include "sanitizer_common/sanitizer_flag_parser.h"<br>
 #include "sanitizer_common/sanitizer_libc.h"<br>
+#if defined(__s390x__) && defined(__linux__)<br>
+// For AvoidCVE_2016_2143.<br>
+#include "sanitizer_common/sanitizer_linux.h"<br>
+#endif<br>
 #include "sanitizer_common/sanitizer_procmaps.h"<br>
 #include "sanitizer_common/sanitizer_stacktrace.h"<br>
 #include "sanitizer_common/sanitizer_symbolizer.h"<br>
@@ -375,6 +379,9 @@ void __msan_init() {<br>
   msan_init_is_running = 1;<br>
   SanitizerToolName = "MemorySanitizer";<br>
<br>
+#if defined(__s390x__) && defined(__linux__)<br>
+  AvoidCVE_2016_2143();<br>
+#endif<br>
   InitTlsSize();<br>
<br>
   CacheBinaryName();<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=266297&r1=266296&r2=266297&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=266297&r1=266296&r2=266297&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Thu Apr 14 07:56:24 2016<br>
@@ -56,6 +56,7 @@<br>
 #include <sys/syscall.h><br>
 #include <sys/time.h><br>
 #include <sys/types.h><br>
+#include <sys/utsname.h><br>
 #include <ucontext.h><br>
 #include <unistd.h><br>
<br>
@@ -1346,6 +1347,72 @@ void MaybeReexec() {<br>
   // No need to re-exec on Linux.<br>
 }<br>
<br>
+#ifdef __s390x__<br>
+static bool FixedCVE_2016_2143() {<br>
+  // Try to determine if the running kernel has a fix for CVE-2016-2143,<br>
+  // return false if in doubt (better safe than sorry).  Distros may want to<br>
+  // adjust this for their own kernels.<br>
+  struct utsname buf;<br>
+  unsigned int major, minor, patch = 0;<br>
+  // This should never fail, but just in case...<br>
+  if (uname(&buf))<br>
+    return false;<br>
+  char *ptr = buf.release;<br>
+  major = internal_simple_strtoll(ptr, &ptr, 10);<br>
+  // At least first 2 should be matched.<br>
+  if (ptr[0] != '.')<br>
+    return false;<br>
+  minor = internal_simple_strtoll(ptr+1, &ptr, 10);<br>
+  // Third is optional.<br>
+  if (ptr[0] == '.')<br>
+    patch = internal_simple_strtoll(ptr+1, &ptr, 10);<br>
+  if (major < 3) {<br>
+    // <3.0 is bad.<br>
+    return false;<br>
+  } else if (major == 3) {<br>
+    // 3.2.79+ is OK.<br>
+    if (minor == 2 && patch >= 79)<br>
+      return true;<br>
+    // Otherwise, bad.<br>
+    return false;<br>
+  } else if (major == 4) {<br>
+    // 4.1.21+ is OK.<br>
+    if (minor == 1 && patch >= 21)<br>
+      return true;<br>
+    // 4.4.6+ is OK.<br>
+    if (minor == 4 && patch >= 6)<br>
+      return true;<br>
+    // Otherwise, OK if 4.5+.<br>
+    return minor >= 5;<br>
+  } else {<br>
+    // Linux 5 and up are fine.<br>
+    return true;<br>
+  }<br>
+}<br>
+<br>
+void AvoidCVE_2016_2143() {<br>
+  // Older kernels are affected by CVE-2016-2143 - they will crash hard<br>
+  // if someone uses 4-level page tables (ie. virtual addresses >= 4TB)<br>
+  // and fork() in the same process.  Unfortunately, sanitizers tend to<br>
+  // require such addresses.  Since this is very likely to crash the whole<br>
+  // machine (sanitizers themselves use fork() for llvm-symbolizer, for one),<br>
+  // abort the process at initialization instead.<br>
+  if (FixedCVE_2016_2143())<br>
+    return;<br>
+  if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))<br>
+    return;<br>
+  Report(<br>
+    "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143.  Using ASan,\n"<br>
+    "MSan or TSan with such kernel can and will crash your machine, or worse.\n"<br>
+    "\n"<br>
+    "If you are certain your kernel is not vulnerable (you have compiled it\n"<br>
+    "yourself, are are using an unrecognized distribution kernel), you can\n"<br>
+    "override this safety check by exporting SANITIZER_IGNORE_CVE_2016_2143\n"<br>
+    "with any value.\n");<br>
+  Die();<br>
+}<br>
+#endif<br>
+<br>
 } // namespace __sanitizer<br>
<br>
 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=266297&r1=266296&r2=266297&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=266297&r1=266296&r2=266297&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h Thu Apr 14 07:56:24 2016<br>
@@ -83,6 +83,11 @@ bool LibraryNameIs(const char *full_name<br>
<br>
 // Call cb for each region mapped by map.<br>
 void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));<br>
+<br>
+#ifdef __s390x__<br>
+// Aborts the process if running on a kernel without a fix for CVE-2016-2143.<br>
+void AvoidCVE_2016_2143();<br>
+#endif<br>
 }  // namespace __sanitizer<br>
<br>
 #endif  // SANITIZER_FREEBSD || SANITIZER_LINUX<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc?rev=266297&r1=266296&r2=266297&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc?rev=266297&r1=266296&r2=266297&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc Thu Apr 14 07:56:24 2016<br>
@@ -247,6 +247,9 @@ static void InitDataSeg() {<br>
 #endif  // #ifndef SANITIZER_GO<br>
<br>
 void InitializePlatformEarly() {<br>
+#ifdef __s390x__<br>
+  AvoidCVE_2016_2143();<br>
+#endif<br>
 #ifdef TSAN_RUNTIME_VMA<br>
   vmaSize =<br>
     (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>