Skip to content

Commit 2aeb303

Browse files
rorthyuxuanchen1997
authored andcommitted
[safestack] Various Solaris fixes (#99290)
Summary: Even with the `-u __safestack_init` link order fixed on Solaris, there are still several safestack test issues left: - While 540fd42 enabled safestack on Solaris in the driver unconditionally, it ignored that Solaris also exists on SPARC and forgot to enable SPARC support for the runtime lib. This patch fixes that. - The tests fail to link with undefined references to `__sanitizer_internal_memset` etc in `safestack.cpp.o` and `interception_linux.cpp.o`. These are from indirectly including `sanitizer_redefine_builtins.h`. Instead of using the implementations from `sanitizer_common` as was done in [[safestack] Various Solaris fixes](#98469), this patch disables the interception as discussed in [Revert "[safestack] Various Solaris fixes"](#98541). A similar issue affects 32-bit Linux/sparc where compiling `safestack.cpp` with `-ftrivial-auto-var-init=pattern` causes the compiler to generate calls to `memset` to initialize a `pthread_attr_t` which is larger than can be handled inline. This is avoided by defining `SANITIZER_COMMON_NO_REDEFINE_BUILTINS` in `safestack.cpp` and also adding definitions of the interceptors that just forward to `libc` for the benefit of `interception_linux.cpp`. - The `pthread*.c` tests `FAIL` with ``` safestack CHECK failed: /vol/llvm/src/llvm-project/local/compiler-rt/lib/safestack/safestack.cpp:227 size ``` The problem is that `pthread_attr_init` initializes the `stacksize` attribute to 0, signifying the default. Unless explicitly overridded, it stays that way. I think this is allowed by XPG7. Since safestack cannot deal with this, I set `size` to the defaults documented in `pthread_create(3C)`. Unfortunately, there's no macro for those values outside of private `libc` headers. - The Solaris `syscall` interface isn't stable. This is not just a theoretical concern, but the syscalls have changed incompatibly several times in the past. Therefore this patch switches the implementations of `TgKill` (where `SYS_lwp_kill` doesn't exist on Solaris 11.4 anyway), `Mmap`, `Munmap`, and `Mprotect` to the same `_REAL*` solution already used in `sanitizer_solaris.cpp`. With those changes, safestack compiles and all tests `PASS`, so the tests are re-enabled for good. Tested on `amd64-pc-solaris2.11`, `sparcv9-sun-solaris2.11`, `x86_64-pc-linux-gnu`, and `sparc64-unknown-linux-gnu`. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250973
1 parent 13c60e3 commit 2aeb303

File tree

4 files changed

+66
-9
lines changed

4 files changed

+66
-9
lines changed

compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
7777
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
7878
${LOONGARCH64})
7979
set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64}
80-
${HEXAGON} ${LOONGARCH64})
80+
${HEXAGON} ${LOONGARCH64} ${SPARC} ${SPARCV9})
8181
set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS64}
8282
${HEXAGON} ${LOONGARCH64})
8383
set(ALL_SCUDO_STANDALONE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}

compiler-rt/lib/safestack/safestack.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,39 @@
1313
//
1414
//===----------------------------------------------------------------------===//
1515

16+
#define SANITIZER_COMMON_NO_REDEFINE_BUILTINS
17+
1618
#include "safestack_platform.h"
1719
#include "safestack_util.h"
20+
#include "sanitizer_common/sanitizer_internal_defs.h"
1821

1922
#include <errno.h>
23+
#include <string.h>
2024
#include <sys/resource.h>
2125

2226
#include "interception/interception.h"
2327

28+
// interception.h drags in sanitizer_redefine_builtins.h, which in turn
29+
// creates references to __sanitizer_internal_memcpy etc. The interceptors
30+
// aren't needed here, so just forward to libc.
31+
extern "C" {
32+
SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memcpy(void *dest,
33+
const void *src,
34+
size_t n) {
35+
return memcpy(dest, src, n);
36+
}
37+
38+
SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memmove(
39+
void *dest, const void *src, size_t n) {
40+
return memmove(dest, src, n);
41+
}
42+
43+
SANITIZER_INTERFACE_ATTRIBUTE void *__sanitizer_internal_memset(void *s, int c,
44+
size_t n) {
45+
return memset(s, c, n);
46+
}
47+
} // extern "C"
48+
2449
using namespace safestack;
2550

2651
// TODO: To make accessing the unsafe stack pointer faster, we plan to
@@ -224,6 +249,17 @@ INTERCEPTOR(int, pthread_create, pthread_t *thread,
224249
pthread_attr_destroy(&tmpattr);
225250
}
226251

252+
#if SANITIZER_SOLARIS
253+
// Solaris pthread_attr_init initializes stacksize to 0 (the default), so
254+
// hardcode the actual values as documented in pthread_create(3C).
255+
if (size == 0)
256+
# if defined(_LP64)
257+
size = 2 * 1024 * 1024;
258+
# else
259+
size = 1024 * 1024;
260+
# endif
261+
#endif
262+
227263
SFS_CHECK(size);
228264
size = RoundUpTo(size, kStackAlign);
229265

compiler-rt/lib/safestack/safestack_platform.h

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "sanitizer_common/sanitizer_platform.h"
1818

1919
#include <dlfcn.h>
20+
#include <errno.h>
2021
#include <stdint.h>
2122
#include <stdio.h>
2223
#include <stdlib.h>
@@ -68,6 +69,24 @@ static void *GetRealLibcAddress(const char *symbol) {
6869
SFS_CHECK(real_##func);
6970
#endif
7071

72+
#if SANITIZER_SOLARIS
73+
# define _REAL(func) _##func
74+
# define DEFINE__REAL(ret_type, func, ...) \
75+
extern "C" ret_type _REAL(func)(__VA_ARGS__)
76+
77+
# if !defined(_LP64) && _FILE_OFFSET_BITS == 64
78+
# define _REAL64(func) _##func##64
79+
# else
80+
# define _REAL64(func) _REAL(func)
81+
# endif
82+
# define DEFINE__REAL64(ret_type, func, ...) \
83+
extern "C" ret_type _REAL64(func)(__VA_ARGS__)
84+
85+
DEFINE__REAL64(void *, mmap, void *a, size_t b, int c, int d, int e, off_t f);
86+
DEFINE__REAL(int, munmap, void *a, size_t b);
87+
DEFINE__REAL(int, mprotect, void *a, size_t b, int c);
88+
#endif
89+
7190
using ThreadId = uint64_t;
7291

7392
inline ThreadId GetTid() {
@@ -91,11 +110,10 @@ inline int TgKill(pid_t pid, ThreadId tid, int sig) {
91110
(void)pid;
92111
return _REAL(_lwp_kill, tid, sig);
93112
#elif SANITIZER_SOLARIS
94-
# ifdef SYS_lwp_kill
95-
return syscall(SYS_lwp_kill, tid, sig);
96-
# else
97-
return -1;
98-
# endif
113+
(void)pid;
114+
errno = thr_kill(tid, sig);
115+
// TgKill is expected to return -1 on error, not an errno.
116+
return errno != 0 ? -1 : 0;
99117
#elif SANITIZER_FREEBSD
100118
return syscall(SYS_thr_kill2, pid, tid, sig);
101119
#else
@@ -110,8 +128,7 @@ inline void *Mmap(void *addr, size_t length, int prot, int flags, int fd,
110128
#elif SANITIZER_FREEBSD && (defined(__aarch64__) || defined(__x86_64__))
111129
return (void *)__syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
112130
#elif SANITIZER_SOLARIS
113-
return (void *)(uintptr_t)syscall(SYS_mmap, addr, length, prot, flags, fd,
114-
offset);
131+
return _REAL64(mmap)(addr, length, prot, flags, fd, offset);
115132
#else
116133
return (void *)syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
117134
#endif
@@ -121,6 +138,8 @@ inline int Munmap(void *addr, size_t length) {
121138
#if SANITIZER_NETBSD
122139
DEFINE__REAL(int, munmap, void *a, size_t b);
123140
return _REAL(munmap, addr, length);
141+
#elif SANITIZER_SOLARIS
142+
return _REAL(munmap)(addr, length);
124143
#else
125144
return syscall(SYS_munmap, addr, length);
126145
#endif
@@ -130,6 +149,8 @@ inline int Mprotect(void *addr, size_t length, int prot) {
130149
#if SANITIZER_NETBSD
131150
DEFINE__REAL(int, mprotect, void *a, size_t b, int c);
132151
return _REAL(mprotect, addr, length, prot);
152+
#elif SANITIZER_SOLARIS
153+
return _REAL(mprotect)(addr, length, prot);
133154
#else
134155
return syscall(SYS_mprotect, addr, length, prot);
135156
#endif

compiler-rt/test/safestack/lit.cfg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@
3333
)
3434
)
3535

36-
if config.host_os not in ["Linux", "FreeBSD", "NetBSD"]:
36+
if config.host_os not in ["Linux", "FreeBSD", "NetBSD", "SunOS"]:
3737
config.unsupported = True

0 commit comments

Comments
 (0)