From ca747e48afa091afd8568df8973dfcbd43b8e334 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 6 Mar 2021 10:32:27 -0800 Subject: [PATCH] [sanitizer] Restrict clock_gettime workaround to glibc The hackery is due to glibc clock_gettime crashing from preinit_array (D40679). 32-bit musl architectures do not define `__NR_clock_gettime` so the code causes a compile error. Tested on Alpine Linux x86-64 (musl) and FreeBSD x86-64. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D96925 --- .../sanitizer_common/sanitizer_common_interceptors.inc | 2 ++ compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp | 4 +++- compiler-rt/lib/sanitizer_common/sanitizer_linux.h | 2 ++ .../lib/sanitizer_common/sanitizer_linux_libcdep.cpp | 15 ++++----------- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index d4b9ea5..f1cf51f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2178,6 +2178,7 @@ INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) { } return res; } +#if SANITIZER_GLIBC namespace __sanitizer { extern "C" { int real_clock_gettime(u32 clk_id, void *tp) { @@ -2187,6 +2188,7 @@ int real_clock_gettime(u32 clk_id, void *tp) { } } // extern "C" } // namespace __sanitizer +#endif INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 2537677..9d4fd06 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -500,11 +500,13 @@ u64 NanoTime() { internal_syscall(SYSCALL(gettimeofday), &tv, 0); return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; } +#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD +#if SANITIZER_GLIBC uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { return internal_syscall(SYSCALL(clock_gettime), clk_id, tp); } -#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD +#endif // SANITIZER_GLIBC // Like getenv, but reads env directly from /proc (on Linux) or parses the // 'environ' array (on some others) and does not use libc. This function diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index 24902d1..41ae072 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -49,7 +49,9 @@ uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); uptr internal_sigaltstack(const void* ss, void* oss); uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset); +#if SANITIZER_GLIBC uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp); +#endif // Linux-only syscalls. #if SANITIZER_LINUX diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp index f20b900..2fff501 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -803,20 +803,13 @@ void LogMessageOnPrintf(const char *str) { #endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_GO +#if SANITIZER_GLIBC && !SANITIZER_GO // glibc crashes when using clock_gettime from a preinit_array function as the // vDSO function pointers haven't been initialized yet. __progname is // initialized after the vDSO function pointers, so if it exists, is not null // and is not empty, we can use clock_gettime. extern "C" SANITIZER_WEAK_ATTRIBUTE char *__progname; -inline bool CanUseVDSO() { - // Bionic is safe, it checks for the vDSO function pointers to be initialized. - if (SANITIZER_ANDROID) - return true; - if (&__progname && __progname && *__progname) - return true; - return false; -} +inline bool CanUseVDSO() { return &__progname && __progname && *__progname; } // MonotonicNanoTime is a timing function that can leverage the vDSO by calling // clock_gettime. real_clock_gettime only exists if clock_gettime is @@ -836,10 +829,10 @@ u64 MonotonicNanoTime() { return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec; } #else -// Non-Linux & Go always use the syscall. +// Non-Linux & Go always use the regular function. u64 MonotonicNanoTime() { timespec ts; - internal_clock_gettime(CLOCK_MONOTONIC, &ts); + clock_gettime(CLOCK_MONOTONIC, &ts); return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec; } #endif // SANITIZER_LINUX && !SANITIZER_GO -- 2.7.4