summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2022-04-07 22:35:24 -0700
committerTom Stellard <tstellar@redhat.com>2022-04-25 20:43:30 -0700
commita36801750327d05d5f8a19aec33819ae3f8f5e35 (patch)
tree937782d97e18220cfca2f7561d2c02338b675519
parent1f4c7b2a9120357c2ee91bc407bf443734df54ec (diff)
downloadllvm-a36801750327d05d5f8a19aec33819ae3f8f5e35.tar.gz
[asan] Always skip first object from dl_iterate_phdr
All platforms return the main executable as the first dl_phdr_info. FreeBSD, NetBSD, Solaris, and Linux-musl place the executable name in the dlpi_name field of this entry. It appears that only Linux-glibc uses the empty string. To make this work generically on all platforms, unconditionally skip the first object (like is currently done for FreeBSD and NetBSD). This fixes first DSO detection on Linux-musl. It also would likely fix detection on Solaris/Illumos if it were to gain PIE support (since dlpi_addr would not be NULL). Additionally, only skip the Linux VDSO on linux. Finally, use the empty string as the "seen first dl_phdr_info" marker rather than (char *)-1. If there was no other object, we would try to dereference it for a string comparison. Reviewed By: MaskRay, vitalybuka Differential Revision: https://reviews.llvm.org/D119515 (cherry picked from commit 795b07f5498c7e5783237418f34d7ea69e801f87)
-rw-r--r--compiler-rt/lib/asan/asan_linux.cpp30
1 files changed, 12 insertions, 18 deletions
diff --git a/compiler-rt/lib/asan/asan_linux.cpp b/compiler-rt/lib/asan/asan_linux.cpp
index 1d92c530bd11..defd81bc19e2 100644
--- a/compiler-rt/lib/asan/asan_linux.cpp
+++ b/compiler-rt/lib/asan/asan_linux.cpp
@@ -131,30 +131,24 @@ static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", info->dlpi_name,
(void *)info->dlpi_addr);
- // Continue until the first dynamic library is found
- if (!info->dlpi_name || info->dlpi_name[0] == 0)
- return 0;
-
- // Ignore vDSO
- if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
- return 0;
+ const char **name = (const char **)data;
-#if SANITIZER_FREEBSD || SANITIZER_NETBSD
// Ignore first entry (the main program)
- char **p = (char **)data;
- if (!(*p)) {
- *p = (char *)-1;
+ if (!*name) {
+ *name = "";
return 0;
}
-#endif
-#if SANITIZER_SOLARIS
- // Ignore executable on Solaris
- if (info->dlpi_addr == 0)
+# if SANITIZER_LINUX
+ // Ignore vDSO. glibc versions earlier than 2.15 (and some patched
+ // by distributors) return an empty name for the vDSO entry, so
+ // detect this as well.
+ if (!info->dlpi_name[0] ||
+ internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
return 0;
-#endif
+# endif
- *(const char **)data = info->dlpi_name;
+ *name = info->dlpi_name;
return 1;
}
@@ -175,7 +169,7 @@ void AsanCheckDynamicRTPrereqs() {
// Ensure that dynamic RT is the first DSO in the list
const char *first_dso_name = nullptr;
dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
- if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
+ if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) {
Report("ASan runtime does not come first in initial library list; "
"you should either link runtime to your application or "
"manually preload it with LD_PRELOAD.\n");