aboutsummaryrefslogtreecommitdiff
path: root/libsanitizer
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2021-03-08 15:52:03 +0100
committerMartin Liska <mliska@suse.cz>2021-03-08 15:55:27 +0100
commit81fee438512460f1be50d91ee5de452f8fe5cc18 (patch)
tree082b41dce09fd3160704746c74a491689536c1b8 /libsanitizer
parent04b4828c6dd215385fde6964a5e13da8a01a78ba (diff)
downloadgcc-81fee438512460f1be50d91ee5de452f8fe5cc18.zip
gcc-81fee438512460f1be50d91ee5de452f8fe5cc18.tar.gz
gcc-81fee438512460f1be50d91ee5de452f8fe5cc18.tar.bz2
libsanitizer: cherry-pick ad294e572bc5c16f9dc420cc994322de6ca3fbfb
libsanitizer/ChangeLog: PR sanitizer/98920 * asan/asan_interceptors.cpp (COMMON_INTERCEPT_FUNCTION_VER): Cherry pick. (COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK): Likewise. * asan/asan_interceptors.h (ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK): Likewise. * sanitizer_common/sanitizer_common_interceptors.inc (COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN): Likewise. (INIT_REGEX): Likewise. * tsan/tsan_interceptors_posix.cpp (COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK): Likewise. gcc/testsuite/ChangeLog: PR sanitizer/98920 * c-c++-common/asan/pr98920.c: New test.
Diffstat (limited to 'libsanitizer')
-rw-r--r--libsanitizer/asan/asan_interceptors.cpp5
-rw-r--r--libsanitizer/asan/asan_interceptors.h7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc19
-rw-r--r--libsanitizer/tsan/tsan_interceptors_posix.cpp2
4 files changed, 31 insertions, 2 deletions
diff --git a/libsanitizer/asan/asan_interceptors.cpp b/libsanitizer/asan/asan_interceptors.cpp
index b19cf25..4e68b3b 100644
--- a/libsanitizer/asan/asan_interceptors.cpp
+++ b/libsanitizer/asan/asan_interceptors.cpp
@@ -90,8 +90,10 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
(void) ctx; \
#define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name)
-#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
+#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
ASAN_INTERCEPT_FUNC_VER(name, ver)
+#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
+ ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
ASAN_WRITE_RANGE(ctx, ptr, size)
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
@@ -687,6 +689,7 @@ void InitializeAsanInterceptors() {
// Intercept threading-related functions
#if ASAN_INTERCEPT_PTHREAD_CREATE
+// TODO: this should probably have an unversioned fallback for newer arches?
#if defined(ASAN_PTHREAD_CREATE_VERSION)
ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
#else
diff --git a/libsanitizer/asan/asan_interceptors.h b/libsanitizer/asan/asan_interceptors.h
index 43cb4e3..56dc34b 100644
--- a/libsanitizer/asan/asan_interceptors.h
+++ b/libsanitizer/asan/asan_interceptors.h
@@ -150,6 +150,13 @@ DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", #name, \
#ver); \
} while (0)
+#define ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
+ do { \
+ if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
+ VReport(1, "AddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \
+ #name, #ver, #name); \
+ } while (0)
+
#else
// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
#define ASAN_INTERCEPT_FUNC(name)
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
index 729eead..2f2787e 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -239,6 +239,23 @@ extern const short *_tolower_tab_;
COMMON_INTERCEPT_FUNCTION(fn)
#endif
+#ifdef __GLIBC__
+// If we could not find the versioned symbol, fall back to an unversioned
+// lookup. This is needed to work around a GLibc bug that causes dlsym
+// with RTLD_NEXT to return the oldest versioned symbol.
+// See https://sourceware.org/bugzilla/show_bug.cgi?id=14932.
+// For certain symbols (e.g. regexec) we have to perform a versioned lookup,
+// but that versioned symbol will only exist for architectures where the
+// oldest Glibc version pre-dates support for that architecture.
+// For example, regexec@GLIBC_2.3.4 exists on x86_64, but not RISC-V.
+// See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98920.
+#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
+ COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(fn, ver)
+#else
+#define COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(fn, ver) \
+ COMMON_INTERCEPT_FUNCTION(fn)
+#endif
+
#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
{ \
@@ -7772,7 +7789,7 @@ INTERCEPTOR(void, regfree, const void *preg) {
}
#define INIT_REGEX \
COMMON_INTERCEPT_FUNCTION(regcomp); \
- COMMON_INTERCEPT_FUNCTION(regexec); \
+ COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(regexec, "GLIBC_2.3.4"); \
COMMON_INTERCEPT_FUNCTION(regerror); \
COMMON_INTERCEPT_FUNCTION(regfree);
#else
diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp b/libsanitizer/tsan/tsan_interceptors_posix.cpp
index 20c2747..aa04d8d 100644
--- a/libsanitizer/tsan/tsan_interceptors_posix.cpp
+++ b/libsanitizer/tsan/tsan_interceptors_posix.cpp
@@ -2227,6 +2227,8 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
INTERCEPT_FUNCTION_VER(name, ver)
+#define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
+ (INTERCEPT_FUNCTION_VER(name, ver) || INTERCEPT_FUNCTION(name))
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \