1 //===-- sanitizer_linux_s390.cc -------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries and implements s390-linux-specific functions from
13 //===----------------------------------------------------------------------===//
15 #include "sanitizer_platform.h"
17 #if SANITIZER_LINUX && SANITIZER_S390
19 #include "sanitizer_libc.h"
20 #include "sanitizer_linux.h"
23 #include <sys/syscall.h>
24 #include <sys/utsname.h>
27 namespace __sanitizer {
29 // --------------- sanitizer_libc.h
30 uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
32 struct s390_mmap_params {
41 (unsigned long)length,
46 (unsigned long)offset,
48 (unsigned long)(offset / 4096),
52 return syscall(__NR_mmap, ¶ms);
54 return syscall(__NR_mmap2, ¶ms);
58 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
59 int *parent_tidptr, void *newtls, int *child_tidptr) {
60 if (!fn || !child_stack)
62 CHECK_EQ(0, (uptr)child_stack % 16);
63 // Minimum frame size.
65 child_stack = (char *)child_stack - 160;
67 child_stack = (char *)child_stack - 96;
69 // Terminate unwind chain.
70 ((unsigned long *)child_stack)[0] = 0;
71 // And pass parameters.
72 ((unsigned long *)child_stack)[1] = (uptr)fn;
73 ((unsigned long *)child_stack)[2] = (uptr)arg;
74 register long res __asm__("r2");
75 register void *__cstack __asm__("r2") = child_stack;
76 register int __flags __asm__("r3") = flags;
77 register int * __ptidptr __asm__("r4") = parent_tidptr;
78 register int * __ctidptr __asm__("r5") = child_tidptr;
79 register void * __newtls __asm__("r6") = newtls;
97 "lmg %%r1, %%r2, 8(%%r15)\n"
99 "lm %%r1, %%r2, 4(%%r15)\n"
103 /* Call _exit(%r2). */
106 /* Return to parent. */
109 : "i"(__NR_clone), "i"(__NR_exit),
119 #if SANITIZER_S390_64
120 static bool FixedCVE_2016_2143() {
121 // Try to determine if the running kernel has a fix for CVE-2016-2143,
122 // return false if in doubt (better safe than sorry). Distros may want to
123 // adjust this for their own kernels.
125 unsigned int major, minor, patch = 0;
126 // This should never fail, but just in case...
129 char *ptr = buf.release;
130 major = internal_simple_strtoll(ptr, &ptr, 10);
131 // At least first 2 should be matched.
134 minor = internal_simple_strtoll(ptr+1, &ptr, 10);
135 // Third is optional.
137 patch = internal_simple_strtoll(ptr+1, &ptr, 10);
141 } else if (major == 3) {
143 if (minor == 2 && patch >= 79)
146 if (minor == 12 && patch >= 58)
150 } else if (major == 4) {
152 if (minor == 1 && patch >= 21)
155 if (minor == 4 && patch >= 6)
157 // Otherwise, OK if 4.5+.
160 // Linux 5 and up are fine.
165 void AvoidCVE_2016_2143() {
166 // Older kernels are affected by CVE-2016-2143 - they will crash hard
167 // if someone uses 4-level page tables (ie. virtual addresses >= 4TB)
168 // and fork() in the same process. Unfortunately, sanitizers tend to
169 // require such addresses. Since this is very likely to crash the whole
170 // machine (sanitizers themselves use fork() for llvm-symbolizer, for one),
171 // abort the process at initialization instead.
172 if (FixedCVE_2016_2143())
174 if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))
177 "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143. Using ASan,\n"
178 "MSan, TSan, DFSan or LSan with such kernel can and will crash your\n"
179 "machine, or worse.\n"
181 "If you are certain your kernel is not vulnerable (you have compiled it\n"
182 "yourself, or are using an unrecognized distribution kernel), you can\n"
183 "override this safety check by exporting SANITIZER_IGNORE_CVE_2016_2143\n"
184 "with any value.\n");
189 } // namespace __sanitizer
191 #endif // SANITIZER_LINUX && SANITIZER_S390