Skip to content

Commit a368017

Browse files
michaelforneytstellar
authored andcommitted
[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 795b07f)
1 parent 1f4c7b2 commit a368017

File tree

1 file changed

+12
-18
lines changed

1 file changed

+12
-18
lines changed

compiler-rt/lib/asan/asan_linux.cpp

+12-18
Original file line numberDiff line numberDiff line change
@@ -131,30 +131,24 @@ static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
131131
VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", info->dlpi_name,
132132
(void *)info->dlpi_addr);
133133

134-
// Continue until the first dynamic library is found
135-
if (!info->dlpi_name || info->dlpi_name[0] == 0)
136-
return 0;
137-
138-
// Ignore vDSO
139-
if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
140-
return 0;
134+
const char **name = (const char **)data;
141135

142-
#if SANITIZER_FREEBSD || SANITIZER_NETBSD
143136
// Ignore first entry (the main program)
144-
char **p = (char **)data;
145-
if (!(*p)) {
146-
*p = (char *)-1;
137+
if (!*name) {
138+
*name = "";
147139
return 0;
148140
}
149-
#endif
150141

151-
#if SANITIZER_SOLARIS
152-
// Ignore executable on Solaris
153-
if (info->dlpi_addr == 0)
142+
# if SANITIZER_LINUX
143+
// Ignore vDSO. glibc versions earlier than 2.15 (and some patched
144+
// by distributors) return an empty name for the vDSO entry, so
145+
// detect this as well.
146+
if (!info->dlpi_name[0] ||
147+
internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
154148
return 0;
155-
#endif
149+
# endif
156150

157-
*(const char **)data = info->dlpi_name;
151+
*name = info->dlpi_name;
158152
return 1;
159153
}
160154

@@ -175,7 +169,7 @@ void AsanCheckDynamicRTPrereqs() {
175169
// Ensure that dynamic RT is the first DSO in the list
176170
const char *first_dso_name = nullptr;
177171
dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
178-
if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
172+
if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) {
179173
Report("ASan runtime does not come first in initial library list; "
180174
"you should either link runtime to your application or "
181175
"manually preload it with LD_PRELOAD.\n");

0 commit comments

Comments
 (0)