diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2013-05-17 12:51:13 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2013-05-17 12:51:13 +0000 |
commit | ff6728f2f88a3939a79de70eaaf856b304b65f0b (patch) | |
tree | 61fe9231e799cb4deaf4a3684f3f08fa2991ed63 | |
parent | 6e23ac606e4fefc69f8df54036614e8bf973e489 (diff) | |
download | bcm5719-llvm-ff6728f2f88a3939a79de70eaaf856b304b65f0b.tar.gz bcm5719-llvm-ff6728f2f88a3939a79de70eaaf856b304b65f0b.zip |
[msan] Unpoison dlpi_name in dl_iterate_phdr interceptor.
llvm-svn: 182093
4 files changed, 69 insertions, 30 deletions
diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc index fde1fb0e78f..fcda7875261 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cc +++ b/compiler-rt/lib/msan/msan_interceptors.cc @@ -815,15 +815,20 @@ INTERCEPTOR(void *, dlopen, const char *filename, int flag) { return (void *)map; } -typedef int (*dl_iterate_phdr_cb)(void *info, SIZE_T size, void *data); +typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size, + void *data); struct dl_iterate_phdr_data { dl_iterate_phdr_cb callback; void *data; }; -static int msan_dl_iterate_phdr_cb(void *info, SIZE_T size, void *data) { - if (info) +static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size, + void *data) { + if (info) { __msan_unpoison(info, size); + if (info->dlpi_name) + __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1); + } dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data; __msan_unpoison_param(3); return cbdata->callback(info, size, cbdata->data); diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index e9361f37c85..1e34b4b0010 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -1475,6 +1475,32 @@ TEST(MemorySanitizer, getrusage) { EXPECT_NOT_POISONED(usage.ru_nivcsw); } +#ifdef __GLIBC__ +extern "C" { + extern void *__libc_stack_end; +} + +static char **GetArgv(void) { + uintptr_t *stack_end = (uintptr_t *)__libc_stack_end; + return (char**)(stack_end + 1); +} + +#else // __GLIBC__ +# error "TODO: port this" +#endif + +// Compute the path to our loadable DSO. We assume it's in the same +// directory. Only use string routines that we intercept so far to do this. +static int PathToLoadable(char *buf, size_t sz) { + char **argv = GetArgv(); + const char *basename = "libmsan_loadable.x86_64.so"; + char *last_slash = strrchr(argv[0], '/'); + assert(last_slash); + int res = snprintf(buf, sz, "%.*s/%s", int(last_slash - argv[0]), argv[0], + basename); + return res < sz ? 0 : res; +} + static void dladdr_testfn() {} TEST(MemorySanitizer, dladdr) { @@ -1503,37 +1529,27 @@ static int dl_phdr_callback(struct dl_phdr_info *info, size_t size, void *data) } TEST(MemorySanitizer, dl_iterate_phdr) { + char path[4096]; + int res = PathToLoadable(path, sizeof(path)); + assert(!res); + + // Having at least one dlopen'ed library in the process makes this more + // entertaining. + void *lib = dlopen(path, RTLD_LAZY); + ASSERT_NE((void*)0, lib); + int count = 0; int result = dl_iterate_phdr(dl_phdr_callback, &count); assert(count > 0); + + dlclose(lib); } -namespace { -#ifdef __GLIBC__ -extern "C" { - extern void *__libc_stack_end; -} - -static char **GetArgv(void) { - uintptr_t *stack_end = (uintptr_t *)__libc_stack_end; - return (char**)(stack_end + 1); -} - -#else // __GLIBC__ -# error "TODO: port this" -#endif TEST(MemorySanitizer, dlopen) { - // Compute the path to our loadable DSO. We assume it's in the same - // directory. Only use string routines that we intercept so far to do this. - char **argv = GetArgv(); - const char *basename = "libmsan_loadable.x86_64.so"; - size_t path_max = strlen(argv[0]) + 1 + strlen(basename) + 1; - char *path = new char[path_max]; - char *last_slash = strrchr(argv[0], '/'); - assert(last_slash); - snprintf(path, path_max, "%.*s/%s", int(last_slash - argv[0]), - argv[0], basename); + char path[4096]; + int res = PathToLoadable(path, sizeof(path)); + assert(!res); // We need to clear shadow for globals when doing dlopen. In order to test // this, we have to poison the shadow for the DSO before we load it. In @@ -1554,8 +1570,6 @@ TEST(MemorySanitizer, dlopen) { EXPECT_POISONED(*dso_global); dlclose(lib); } - - delete[] path; } // Regression test for a crash in dlopen() interceptor. @@ -1564,7 +1578,6 @@ TEST(MemorySanitizer, dlopenFailed) { void *lib = dlopen(path, RTLD_LAZY); ASSERT_EQ(0, lib); } -} // namespace TEST(MemorySanitizer, scanf) { const char *input = "42 hello"; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index 1beab897bd0..f9014db3088 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -38,6 +38,7 @@ #endif // !SANITIZER_ANDROID #if SANITIZER_LINUX +#include <link.h> #include <sys/vfs.h> #include <sys/epoll.h> #endif // SANITIZER_LINUX @@ -120,4 +121,15 @@ namespace __sanitizer { COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t)); COMPILER_CHECK(sizeof(__sanitizer::struct_sigaction_max_sz) >= sizeof(__sanitizer::struct_sigaction_sz)); +#if SANITIZER_LINUX +COMPILER_CHECK(offsetof(struct __sanitizer_dl_phdr_info, dlpi_addr) == + offsetof(struct dl_phdr_info, dlpi_addr)); +COMPILER_CHECK(offsetof(struct __sanitizer_dl_phdr_info, dlpi_name) == + offsetof(struct dl_phdr_info, dlpi_name)); +COMPILER_CHECK(offsetof(struct __sanitizer_dl_phdr_info, dlpi_phdr) == + offsetof(struct dl_phdr_info, dlpi_phdr)); +COMPILER_CHECK(offsetof(struct __sanitizer_dl_phdr_info, dlpi_phnum) == + offsetof(struct dl_phdr_info, dlpi_phnum)); +#endif + #endif // SANITIZER_LINUX || SANITIZER_MAC diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index ae960f73484..c923ff3ae8c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -74,6 +74,15 @@ namespace __sanitizer { extern uptr sig_dfl; uptr __sanitizer_in_addr_sz(int af); + +#if SANITIZER_LINUX + struct __sanitizer_dl_phdr_info { + uptr dlpi_addr; + const char *dlpi_name; + const void *dlpi_phdr; + short dlpi_phnum; + }; +#endif } // namespace __sanitizer #endif |