aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt/lib
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib')
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.cpp46
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.h1
-rw-r--r--compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h2
-rw-r--r--compiler-rt/lib/scudo/standalone/linux.cpp6
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp24
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp49
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp6
8 files changed, 120 insertions, 18 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index 7c9a08b..0f613f0 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -58,13 +58,20 @@ namespace __asan {
static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
#if SANITIZER_INTERCEPT_STRNLEN
- if (REAL(strnlen)) {
+ if (REAL(strnlen))
return REAL(strnlen)(s, maxlen);
- }
-#endif
+# endif
return internal_strnlen(s, maxlen);
}
+static inline uptr MaybeRealWcsnlen(const wchar_t* s, uptr maxlen) {
+# if SANITIZER_INTERCEPT_WCSNLEN
+ if (REAL(wcsnlen))
+ return REAL(wcsnlen)(s, maxlen);
+# endif
+ return internal_wcsnlen(s, maxlen);
+}
+
void SetThreadName(const char *name) {
AsanThread *t = GetCurrentThread();
if (t)
@@ -570,6 +577,20 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) {
return REAL(strcpy)(to, from);
}
+INTERCEPTOR(wchar_t*, wcscpy, wchar_t* to, const wchar_t* from) {
+ void* ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, wcscpy);
+ if (!TryAsanInitFromRtl())
+ return REAL(wcscpy)(to, from);
+ if (flags()->replace_str) {
+ uptr size = (internal_wcslen(from) + 1) * sizeof(wchar_t);
+ CHECK_RANGES_OVERLAP("wcscpy", to, size, from, size);
+ ASAN_READ_RANGE(ctx, from, size);
+ ASAN_WRITE_RANGE(ctx, to, size);
+ }
+ return REAL(wcscpy)(to, from);
+}
+
// Windows doesn't always define the strdup identifier,
// and when it does it's a macro defined to either _strdup
// or _strdup_dbg, _strdup_dbg ends up calling _strdup, so
@@ -633,6 +654,20 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, usize size) {
return REAL(strncpy)(to, from, size);
}
+INTERCEPTOR(wchar_t*, wcsncpy, wchar_t* to, const wchar_t* from, uptr size) {
+ void* ctx;
+ ASAN_INTERCEPTOR_ENTER(ctx, wcsncpy);
+ AsanInitFromRtl();
+ if (flags()->replace_str) {
+ uptr from_size =
+ Min(size, MaybeRealWcsnlen(from, size) + 1) * sizeof(wchar_t);
+ CHECK_RANGES_OVERLAP("wcsncpy", to, from_size, from, from_size);
+ ASAN_READ_RANGE(ctx, from, from_size);
+ ASAN_WRITE_RANGE(ctx, to, size * sizeof(wchar_t));
+ }
+ return REAL(wcsncpy)(to, from, size);
+}
+
template <typename Fn>
static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
char **endptr, int base)
@@ -809,6 +844,11 @@ void InitializeAsanInterceptors() {
ASAN_INTERCEPT_FUNC(strncat);
ASAN_INTERCEPT_FUNC(strncpy);
ASAN_INTERCEPT_FUNC(strdup);
+
+ // Intercept wcs* functions.
+ ASAN_INTERCEPT_FUNC(wcscpy);
+ ASAN_INTERCEPT_FUNC(wcsncpy);
+
# if ASAN_INTERCEPT___STRDUP
ASAN_INTERCEPT_FUNC(__strdup);
#endif
diff --git a/compiler-rt/lib/asan/asan_interceptors.h b/compiler-rt/lib/asan/asan_interceptors.h
index 3e2386e..2d551cf 100644
--- a/compiler-rt/lib/asan/asan_interceptors.h
+++ b/compiler-rt/lib/asan/asan_interceptors.h
@@ -129,6 +129,7 @@ DECLARE_REAL(char*, strchr, const char *str, int c)
DECLARE_REAL(SIZE_T, strlen, const char *s)
DECLARE_REAL(char*, strncpy, char *to, const char *from, SIZE_T size)
DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen)
+DECLARE_REAL(SIZE_T, wcsnlen, const wchar_t* s, SIZE_T maxlen)
DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
# if !SANITIZER_APPLE
diff --git a/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp b/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp
index 4a69b66..46e0e90 100644
--- a/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp
@@ -63,6 +63,10 @@ INTERCEPT_LIBRARY_FUNCTION_ASAN(strpbrk);
INTERCEPT_LIBRARY_FUNCTION_ASAN(strspn);
INTERCEPT_LIBRARY_FUNCTION_ASAN(strstr);
INTERCEPT_LIBRARY_FUNCTION_ASAN(strtok);
+INTERCEPT_LIBRARY_FUNCTION_ASAN(wcscat);
+INTERCEPT_LIBRARY_FUNCTION_ASAN(wcscpy);
+INTERCEPT_LIBRARY_FUNCTION_ASAN(wcsncat);
+INTERCEPT_LIBRARY_FUNCTION_ASAN(wcsncpy);
INTERCEPT_LIBRARY_FUNCTION_ASAN(wcslen);
INTERCEPT_LIBRARY_FUNCTION_ASAN(wcsnlen);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 29987de..88ecd7e 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -551,7 +551,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_WCSLEN 1
-#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
+#define SANITIZER_INTERCEPT_WCSCAT (SI_POSIX || SI_WINDOWS)
#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)
#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID
diff --git a/compiler-rt/lib/scudo/standalone/linux.cpp b/compiler-rt/lib/scudo/standalone/linux.cpp
index 6cc8e0c..57171ed 100644
--- a/compiler-rt/lib/scudo/standalone/linux.cpp
+++ b/compiler-rt/lib/scudo/standalone/linux.cpp
@@ -192,6 +192,12 @@ bool getRandom(void *Buffer, uptr Length, UNUSED bool Blocking) {
syscall(SYS_getrandom, Buffer, Length, Blocking ? 0 : GRND_NONBLOCK);
if (ReadBytes == static_cast<ssize_t>(Length))
return true;
+ // If this system call is not implemented in the kernel, then we will try
+ // and use /dev/urandom. Otherwise, if the syscall fails, return false
+ // assuming that trying to read /dev/urandom will cause a delay waiting for
+ // the random data to be usable.
+ if (errno != ENOSYS)
+ return false;
#endif // defined(SYS_getrandom)
// Up to 256 bytes, a read off /dev/urandom will not be interrupted.
// Blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom.
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index b46a810..37c69b1 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -1130,6 +1130,22 @@ TSAN_INTERCEPTOR(int, pthread_create,
TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
+#if SANITIZER_ANDROID
+ {
+ // In Bionic, if the target thread has already exited when pthread_detach is
+ // called, pthread_detach will call pthread_join internally to clean it up.
+ // In that case, the thread has already been consumed by the pthread_detach
+ // interceptor.
+ Tid tid = ctx->thread_registry.FindThread(
+ [](ThreadContextBase* tctx, void* arg) {
+ return tctx->user_id == (uptr)arg;
+ },
+ th);
+ if (tid == kInvalidTid) {
+ return REAL(pthread_join)(th, ret);
+ }
+ }
+#endif
Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
ThreadIgnoreBegin(thr, pc);
int res = BLOCK_REAL(pthread_join)(th, ret);
@@ -2412,7 +2428,11 @@ TSAN_INTERCEPTOR(int, vfork, int fake) {
}
#endif
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
+// Bionic's pthread_create internally calls clone. When the CLONE_THREAD flag is
+// set, clone does not create a new process but a new thread. This is a
+// workaround for Android. Disabling the interception of clone solves the
+// problem in most scenarios.
TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,
void *arg, int *parent_tid, void *tls, pid_t *child_tid) {
SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,
@@ -3135,7 +3155,7 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(fork);
TSAN_INTERCEPT(vfork);
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_ANDROID
TSAN_INTERCEPT(clone);
#endif
#if !SANITIZER_ANDROID
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
index 4b55aab..6b65387 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
@@ -486,8 +486,20 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
// Reverse operation of libc stack pointer mangling
static uptr UnmangleLongJmpSp(uptr mangled_sp) {
-#if defined(__x86_64__)
-# if SANITIZER_LINUX
+# if SANITIZER_ANDROID
+ if (longjmp_xor_key == 0) {
+ // bionic libc initialization process: __libc_init_globals ->
+ // __libc_init_vdso (calls strcmp) -> __libc_init_setjmp_cookie. strcmp is
+ // intercepted by TSan, so during TSan initialization the setjmp_cookie
+ // remains uninitialized. On Android, longjmp_xor_key must be set on first
+ // use.
+ InitializeLongjmpXorKey();
+ CHECK_NE(longjmp_xor_key, 0);
+ }
+# endif
+
+# if defined(__x86_64__)
+# if SANITIZER_LINUX
// Reverse of:
// xor %fs:0x30, %rsi
// rol $0x11, %rsi
@@ -542,13 +554,23 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
# else
# define LONG_JMP_SP_ENV_SLOT 2
# endif
-#elif SANITIZER_LINUX
-# ifdef __aarch64__
-# define LONG_JMP_SP_ENV_SLOT 13
-# elif defined(__loongarch__)
-# define LONG_JMP_SP_ENV_SLOT 1
-# elif defined(__mips64)
-# define LONG_JMP_SP_ENV_SLOT 1
+# elif SANITIZER_ANDROID
+# ifdef __aarch64__
+# define LONG_JMP_SP_ENV_SLOT 3
+# elif SANITIZER_RISCV64
+# define LONG_JMP_SP_ENV_SLOT 3
+# elif defined(__x86_64__)
+# define LONG_JMP_SP_ENV_SLOT 6
+# else
+# error unsupported
+# endif
+# elif SANITIZER_LINUX
+# ifdef __aarch64__
+# define LONG_JMP_SP_ENV_SLOT 13
+# elif defined(__loongarch__)
+# define LONG_JMP_SP_ENV_SLOT 1
+# elif defined(__mips64)
+# define LONG_JMP_SP_ENV_SLOT 1
# elif SANITIZER_RISCV64
# define LONG_JMP_SP_ENV_SLOT 13
# elif defined(__s390x__)
@@ -556,7 +578,7 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
# else
# define LONG_JMP_SP_ENV_SLOT 6
# endif
-#endif
+# endif
uptr ExtractLongJmpSp(uptr *env) {
uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
@@ -653,7 +675,12 @@ ThreadState *cur_thread() {
}
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
}
- return thr;
+
+ // Skia calls mallopt(M_THREAD_DISABLE_MEM_INIT, 1), which sets the least
+ // significant bit of TLS_SLOT_SANITIZER to 1. Scudo allocator uses this bit
+ // as a flag to disable memory initialization. This is a workaround to get the
+ // correct ThreadState pointer.
+ reinterpret_cast<ThreadState*>(addr & ~1ULL);
}
void set_cur_thread(ThreadState *thr) {
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
index b1464cc..978d853 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
@@ -206,10 +206,14 @@ void ThreadStart(ThreadState *thr, Tid tid, ThreadID os_id,
}
#endif
-#if !SANITIZER_GO
+#if !SANITIZER_GO && !SANITIZER_ANDROID
// Don't imitate stack/TLS writes for the main thread,
// because its initialization is synchronized with all
// subsequent threads anyway.
+ // Because thr is created by MmapOrDie, the thr object
+ // is not in tls, the pointer to the thr object is in
+ // TLS_SLOT_SANITIZER slot. So skip this check on
+ // Android platform.
if (tid != kMainTid) {
if (stk_addr && stk_size) {
const uptr pc = StackTrace::GetNextInstructionPc(