diff options
-rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 1 | ||||
-rw-r--r-- | compiler-rt/lib/dfsan/dfsan.cc | 1 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lsan.cc | 1 | ||||
-rw-r--r-- | compiler-rt/lib/msan/msan.cc | 1 | ||||
-rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_common.h | 10 | ||||
-rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc | 69 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 1 |
7 files changed, 84 insertions, 0 deletions
diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 47c726b4e0c..0b7a1dc6b5d 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -415,6 +415,7 @@ static void AsanInitInternal() { AsanCheckIncompatibleRT(); AsanCheckDynamicRTPrereqs(); + AvoidCVE_2016_2143(); SetCanPoisonMemory(flags()->poison_heap); SetMallocContextSize(common_flags()->malloc_context_size); diff --git a/compiler-rt/lib/dfsan/dfsan.cc b/compiler-rt/lib/dfsan/dfsan.cc index 0979c6936ae..4156000a1cc 100644 --- a/compiler-rt/lib/dfsan/dfsan.cc +++ b/compiler-rt/lib/dfsan/dfsan.cc @@ -368,6 +368,7 @@ static void InitializeFlags() { } static void InitializePlatformEarly() { + AvoidCVE_2016_2143(); #ifdef DFSAN_RUNTIME_VMA __dfsan::vmaSize = (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); diff --git a/compiler-rt/lib/lsan/lsan.cc b/compiler-rt/lib/lsan/lsan.cc index 9c6735919b8..c7c34299147 100644 --- a/compiler-rt/lib/lsan/lsan.cc +++ b/compiler-rt/lib/lsan/lsan.cc @@ -72,6 +72,7 @@ extern "C" void __lsan_init() { lsan_init_is_running = true; SanitizerToolName = "LeakSanitizer"; CacheBinaryName(); + AvoidCVE_2016_2143(); InitializeFlags(); InitCommonLsan(); InitializeAllocator(); diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc index cecbfe06a02..52eda77e6ba 100644 --- a/compiler-rt/lib/msan/msan.cc +++ b/compiler-rt/lib/msan/msan.cc @@ -375,6 +375,7 @@ void __msan_init() { msan_init_is_running = 1; SanitizerToolName = "MemorySanitizer"; + AvoidCVE_2016_2143(); InitTlsSize(); CacheBinaryName(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 4cf5b7e77bd..5aaedde59f6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -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, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc index 03a19ea97e4..27c3c7d086c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_s390.cc @@ -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 *), void *child_stack, int flags, void *arg, 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 diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index 3cbc0b569d1..f19a2a0ab9f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -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. |