1 //===-- sanitizer_linux_s390.cpp ------------------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // This file is shared between AddressSanitizer and ThreadSanitizer
10 // run-time libraries and implements s390-linux-specific functions from
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_platform.h"
16 #if SANITIZER_LINUX && SANITIZER_S390
20 # include <sys/syscall.h>
21 # include <sys/utsname.h>
24 # include "sanitizer_libc.h"
25 # include "sanitizer_linux.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
{
40 (unsigned long)addr
, (unsigned long)length
, (unsigned long)prot
,
41 (unsigned long)flags
, (unsigned long)fd
,
43 (unsigned long)offset
,
45 (unsigned long)(offset
/ 4096),
49 return syscall(__NR_mmap
, ¶ms
);
51 return syscall(__NR_mmap2
, ¶ms
);
55 uptr
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
) {
61 CHECK_EQ(0, (uptr
)child_stack
% 16);
62 // Minimum frame size.
64 child_stack
= (char *)child_stack
- 160;
66 child_stack
= (char *)child_stack
- 96;
68 // 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
;
96 "lmg %%r1, %%r2, 8(%%r15)\n"
98 "lm %%r1, %%r2, 4(%%r15)\n"
102 /* Call _exit(%r2). */
105 /* Return to parent. */
108 : "i"(__NR_clone
), "i"(__NR_exit
), "r"(__cstack
), "r"(__flags
),
109 "r"(__ptidptr
), "r"(__ctidptr
), "r"(__newtls
)
111 if (res
>= (uptr
)-4095) {
118 # if SANITIZER_S390_64
119 static 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 to
122 // adjust this for their own kernels.
124 unsigned int major
, minor
, patch
= 0;
125 // This should never fail, but just in case...
126 if (internal_uname(&buf
))
128 const char *ptr
= buf
.release
;
129 major
= internal_simple_strtoll(ptr
, &ptr
, 10);
130 // At least first 2 should be matched.
133 minor
= internal_simple_strtoll(ptr
+ 1, &ptr
, 10);
134 // Third is optional.
136 patch
= internal_simple_strtoll(ptr
+ 1, &ptr
, 10);
138 if (major
== 2 && minor
== 6 && patch
== 32 && ptr
[0] == '-' &&
139 internal_strstr(ptr
, ".el6")) {
141 int r1
= internal_simple_strtoll(ptr
+ 1, &ptr
, 10);
142 if (r1
>= 657) // 2.6.32-657.el6 or later
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 later
152 } else if (major
== 3) {
154 if (minor
== 2 && patch
>= 79)
157 if (minor
== 12 && patch
>= 58)
159 if (minor
== 10 && patch
== 0 && ptr
[0] == '-' &&
160 internal_strstr(ptr
, ".el7")) {
162 int r1
= internal_simple_strtoll(ptr
+ 1, &ptr
, 10);
163 if (r1
>= 426) // 3.10.0-426.el7 or later
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 later
173 } else if (major
== 4) {
175 if (minor
== 1 && patch
>= 21)
178 if (minor
== 4 && patch
>= 6)
180 if (minor
== 4 && patch
== 0 && ptr
[0] == '-' &&
181 internal_strstr(buf
.version
, "Ubuntu")) {
182 // Check Ubuntu 16.04
183 int r1
= internal_simple_strtoll(ptr
+ 1, &ptr
, 10);
184 if (r1
>= 13) // 4.4.0-13 or later
187 // Otherwise, OK if 4.5+.
190 // Linux 5 and up are fine.
195 void AvoidCVE_2016_2143() {
196 // Older kernels are affected by CVE-2016-2143 - they will crash hard
197 // if someone uses 4-level page tables (ie. virtual addresses >= 4TB)
198 // and fork() in the same process. Unfortunately, sanitizers tend to
199 // require such addresses. Since this is very likely to crash the whole
200 // machine (sanitizers themselves use fork() for llvm-symbolizer, for one),
201 // abort the process at initialization instead.
202 if (FixedCVE_2016_2143())
204 if (GetEnv("SANITIZER_IGNORE_CVE_2016_2143"))
207 "ERROR: Your kernel seems to be vulnerable to CVE-2016-2143. Using "
209 "MSan, TSan, DFSan or LSan with such kernel can and will crash your\n"
210 "machine, or worse.\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");
220 } // namespace __sanitizer
222 #endif // SANITIZER_LINUX && SANITIZER_S390