1 //===-- sanitizer_linux_s390.cc -------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries and implements s390-linux-specific functions from
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_platform.h"
15 #if SANITIZER_LINUX && SANITIZER_S390
17 #include "sanitizer_libc.h"
18 #include "sanitizer_linux.h"
21 #include <sys/syscall.h>
22 #include <sys/utsname.h>
25 namespace __sanitizer
{
27 // --------------- sanitizer_libc.h
28 uptr
internal_mmap(void *addr
, uptr length
, int prot
, int flags
, int fd
,
30 struct s390_mmap_params
{
39 (unsigned long)length
,
44 (unsigned long)offset
,
46 (unsigned long)(offset
/ 4096),
50 return syscall(__NR_mmap
, ¶ms
);
52 return syscall(__NR_mmap2
, ¶ms
);
56 uptr
internal_clone(int (*fn
)(void *), void *child_stack
, int flags
, void *arg
,
57 int *parent_tidptr
, void *newtls
, int *child_tidptr
) {
58 if (!fn
|| !child_stack
)
60 CHECK_EQ(0, (uptr
)child_stack
% 16);
61 // Minimum frame size.
63 child_stack
= (char *)child_stack
- 160;
65 child_stack
= (char *)child_stack
- 96;
67 // Terminate unwind chain.
68 ((unsigned long *)child_stack
)[0] = 0;
69 // And pass parameters.
70 ((unsigned long *)child_stack
)[1] = (uptr
)fn
;
71 ((unsigned long *)child_stack
)[2] = (uptr
)arg
;
72 register long res
__asm__("r2");
73 register void *__cstack
__asm__("r2") = child_stack
;
74 register int __flags
__asm__("r3") = flags
;
75 register int * __ptidptr
__asm__("r4") = parent_tidptr
;
76 register int * __ctidptr
__asm__("r5") = child_tidptr
;
77 register void * __newtls
__asm__("r6") = newtls
;
95 "lmg %%r1, %%r2, 8(%%r15)\n"
97 "lm %%r1, %%r2, 4(%%r15)\n"
101 /* Call _exit(%r2). */
104 /* Return to parent. */
107 : "i"(__NR_clone
), "i"(__NR_exit
),
117 #if SANITIZER_S390_64
118 static bool FixedCVE_2016_2143() {
119 // Try to determine if the running kernel has a fix for CVE-2016-2143,
120 // return false if in doubt (better safe than sorry). Distros may want to
121 // adjust this for their own kernels.
123 unsigned int major
, minor
, patch
= 0;
124 // This should never fail, but just in case...
127 char *ptr
= buf
.release
;
128 major
= internal_simple_strtoll(ptr
, &ptr
, 10);
129 // At least first 2 should be matched.
132 minor
= internal_simple_strtoll(ptr
+1, &ptr
, 10);
133 // Third is optional.
135 patch
= internal_simple_strtoll(ptr
+1, &ptr
, 10);
137 if (major
== 2 && minor
== 6 && patch
== 32 && ptr
[0] == '-' &&
138 internal_strstr(ptr
, ".el6")) {
140 int r1
= internal_simple_strtoll(ptr
+1, &ptr
, 10);
141 if (r1
>= 657) // 2.6.32-657.el6 or later
143 if (r1
== 642 && ptr
[0] == '.') {
144 int r2
= internal_simple_strtoll(ptr
+1, &ptr
, 10);
145 if (r2
>= 9) // 2.6.32-642.9.1.el6 or later
151 } else if (major
== 3) {
153 if (minor
== 2 && patch
>= 79)
156 if (minor
== 12 && patch
>= 58)
158 if (minor
== 10 && patch
== 0 && ptr
[0] == '-' &&
159 internal_strstr(ptr
, ".el7")) {
161 int r1
= internal_simple_strtoll(ptr
+1, &ptr
, 10);
162 if (r1
>= 426) // 3.10.0-426.el7 or later
164 if (r1
== 327 && ptr
[0] == '.') {
165 int r2
= internal_simple_strtoll(ptr
+1, &ptr
, 10);
166 if (r2
>= 27) // 3.10.0-327.27.1.el7 or later
172 } else if (major
== 4) {
174 if (minor
== 1 && patch
>= 21)
177 if (minor
== 4 && patch
>= 6)
179 if (minor
== 4 && patch
== 0 && ptr
[0] == '-' &&
180 internal_strstr(buf
.version
, "Ubuntu")) {
181 // Check Ubuntu 16.04
182 int r1
= internal_simple_strtoll(ptr
+1, &ptr
, 10);
183 if (r1
>= 13) // 4.4.0-13 or later
186 // Otherwise, OK if 4.5+.
189 // Linux 5 and up are fine.
194 void AvoidCVE_2016_2143() {
195 // Older kernels are affected by CVE-2016-2143 - they will crash hard
196 // if someone uses 4-level page tables (ie. virtual addresses >= 4TB)
197 // and fork() in the same process. Unfortunately, sanitizers tend to
198 // require such addresses. Since this is very likely to crash the whole
199 // machine (sanitizers themselves use fork() for llvm-symbolizer, for one),
200 // abort the process at initialization instead.
201 if (FixedCVE_2016_2143())
203 if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))
206 "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143. Using ASan,\n"
207 "MSan, TSan, DFSan or LSan with such kernel can and will crash your\n"
208 "machine, or worse.\n"
210 "If you are certain your kernel is not vulnerable (you have compiled it\n"
211 "yourself, or are using an unrecognized distribution kernel), you can\n"
212 "override this safety check by exporting SANITIZER_IGNORE_CVE_2016_2143\n"
213 "with any value.\n");
218 } // namespace __sanitizer
220 #endif // SANITIZER_LINUX && SANITIZER_S390