brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.6 KiB · 8523b54 Raw
223 lines · cpp
1//===-- sanitizer_linux_s390.cpp ------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is shared between AddressSanitizer and ThreadSanitizer10// run-time libraries and implements s390-linux-specific functions from11// sanitizer_libc.h.12//===----------------------------------------------------------------------===//13 14#include "sanitizer_platform.h"15 16#if SANITIZER_LINUX && SANITIZER_S39017 18#  include <dlfcn.h>19#  include <errno.h>20#  include <sys/syscall.h>21#  include <sys/utsname.h>22#  include <unistd.h>23 24#  include "sanitizer_libc.h"25#  include "sanitizer_linux.h"26 27namespace __sanitizer {28 29// --------------- sanitizer_libc.h30uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,31                   u64 offset) {32  struct s390_mmap_params {33    unsigned long addr;34    unsigned long length;35    unsigned long prot;36    unsigned long flags;37    unsigned long fd;38    unsigned long offset;39  } params = {40      (unsigned long)addr,   (unsigned long)length, (unsigned long)prot,41      (unsigned long)flags,  (unsigned long)fd,42#  ifdef __s390x__43      (unsigned long)offset,44#  else45    (unsigned long)(offset / 4096),46#  endif47  };48#  ifdef __s390x__49  return syscall(__NR_mmap, &params);50#  else51  return syscall(__NR_mmap2, &params);52#  endif53}54 55uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,56                    int *parent_tidptr, void *newtls, int *child_tidptr) {57  if (!fn || !child_stack) {58    errno = EINVAL;59    return -1;60  }61  CHECK_EQ(0, (uptr)child_stack % 16);62  // Minimum frame size.63#  ifdef __s390x__64  child_stack = (char *)child_stack - 160;65#  else66  child_stack = (char *)child_stack - 96;67#  endif68  // Terminate unwind chain.69  ((unsigned long *)child_stack)[0] = 0;70  // And pass parameters.71  ((unsigned long *)child_stack)[1] = (uptr)fn;72  ((unsigned long *)child_stack)[2] = (uptr)arg;73  register uptr res __asm__("r2");74  register void *__cstack __asm__("r2") = child_stack;75  register long __flags __asm__("r3") = flags;76  register int *__ptidptr __asm__("r4") = parent_tidptr;77  register int *__ctidptr __asm__("r5") = child_tidptr;78  register void *__newtls __asm__("r6") = newtls;79 80  __asm__ __volatile__(81      /* Clone. */82      "svc    %1\n"83 84  /* if (%r2 != 0)85   *   return;86   */87#  ifdef __s390x__88      "cghi   %%r2, 0\n"89#  else90      "chi    %%r2, 0\n"91#  endif92      "jne    1f\n"93 94  /* Call "fn(arg)". */95#  ifdef __s390x__96      "lmg    %%r1, %%r2, 8(%%r15)\n"97#  else98      "lm     %%r1, %%r2, 4(%%r15)\n"99#  endif100      "basr   %%r14, %%r1\n"101 102      /* Call _exit(%r2). */103      "svc %2\n"104 105      /* Return to parent. */106      "1:\n"107      : "=r"(res)108      : "i"(__NR_clone), "i"(__NR_exit), "r"(__cstack), "r"(__flags),109        "r"(__ptidptr), "r"(__ctidptr), "r"(__newtls)110      : "memory", "cc");111  if (res >= (uptr)-4095) {112    errno = -res;113    return -1;114  }115  return res;116}117 118#  if SANITIZER_S390_64119static bool FixedCVE_2016_2143() {120  // Try to determine if the running kernel has a fix for CVE-2016-2143,121  // return false if in doubt (better safe than sorry).  Distros may want to122  // adjust this for their own kernels.123  struct utsname buf;124  unsigned int major, minor, patch = 0;125  // This should never fail, but just in case...126  if (internal_uname(&buf))127    return false;128  const char *ptr = buf.release;129  major = internal_simple_strtoll(ptr, &ptr, 10);130  // At least first 2 should be matched.131  if (ptr[0] != '.')132    return false;133  minor = internal_simple_strtoll(ptr + 1, &ptr, 10);134  // Third is optional.135  if (ptr[0] == '.')136    patch = internal_simple_strtoll(ptr + 1, &ptr, 10);137  if (major < 3) {138    if (major == 2 && minor == 6 && patch == 32 && ptr[0] == '-' &&139        internal_strstr(ptr, ".el6")) {140      // Check RHEL6141      int r1 = internal_simple_strtoll(ptr + 1, &ptr, 10);142      if (r1 >= 657)  // 2.6.32-657.el6 or later143        return true;144      if (r1 == 642 && ptr[0] == '.') {145        int r2 = internal_simple_strtoll(ptr + 1, &ptr, 10);146        if (r2 >= 9)  // 2.6.32-642.9.1.el6 or later147          return true;148      }149    }150    // <3.0 is bad.151    return false;152  } else if (major == 3) {153    // 3.2.79+ is OK.154    if (minor == 2 && patch >= 79)155      return true;156    // 3.12.58+ is OK.157    if (minor == 12 && patch >= 58)158      return true;159    if (minor == 10 && patch == 0 && ptr[0] == '-' &&160        internal_strstr(ptr, ".el7")) {161      // Check RHEL7162      int r1 = internal_simple_strtoll(ptr + 1, &ptr, 10);163      if (r1 >= 426)  // 3.10.0-426.el7 or later164        return true;165      if (r1 == 327 && ptr[0] == '.') {166        int r2 = internal_simple_strtoll(ptr + 1, &ptr, 10);167        if (r2 >= 27)  // 3.10.0-327.27.1.el7 or later168          return true;169      }170    }171    // Otherwise, bad.172    return false;173  } else if (major == 4) {174    // 4.1.21+ is OK.175    if (minor == 1 && patch >= 21)176      return true;177    // 4.4.6+ is OK.178    if (minor == 4 && patch >= 6)179      return true;180    if (minor == 4 && patch == 0 && ptr[0] == '-' &&181        internal_strstr(buf.version, "Ubuntu")) {182      // Check Ubuntu 16.04183      int r1 = internal_simple_strtoll(ptr + 1, &ptr, 10);184      if (r1 >= 13)  // 4.4.0-13 or later185        return true;186    }187    // Otherwise, OK if 4.5+.188    return minor >= 5;189  } else {190    // Linux 5 and up are fine.191    return true;192  }193}194 195void AvoidCVE_2016_2143() {196  // Older kernels are affected by CVE-2016-2143 - they will crash hard197  // if someone uses 4-level page tables (ie. virtual addresses >= 4TB)198  // and fork() in the same process.  Unfortunately, sanitizers tend to199  // require such addresses.  Since this is very likely to crash the whole200  // machine (sanitizers themselves use fork() for llvm-symbolizer, for one),201  // abort the process at initialization instead.202  if (FixedCVE_2016_2143())203    return;204  if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))205    return;206  Report(207      "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143.  Using "208      "ASan,\n"209      "MSan, TSan, DFSan or LSan with such kernel can and will crash your\n"210      "machine, or worse.\n"211      "\n"212      "If you are certain your kernel is not vulnerable (you have compiled it\n"213      "yourself, or are using an unrecognized distribution kernel), you can\n"214      "override this safety check by exporting SANITIZER_IGNORE_CVE_2016_2143\n"215      "with any value.\n");216  Die();217}218#  endif219 220}  // namespace __sanitizer221 222#endif  // SANITIZER_LINUX && SANITIZER_S390223