From faba61a7bc814fb94a5a3d452570efc0ce4e0214 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 9 Jul 2013 12:07:59 +0000 Subject: [PATCH] [sanitizer] Support GLOB_ALTDIRFUNC in glob interceptor. llvm-svn: 185932 --- compiler-rt/lib/asan/asan_interceptors.cc | 3 + .../msan/lit_tests/Linux/glob_altdirfunc.cc | 77 +++++++++++++++++++ compiler-rt/lib/msan/msan_interceptors.cc | 2 + .../sanitizer_common_interceptors.inc | 52 +++++++++++++ .../sanitizer_platform_limits_posix.cc | 10 ++- .../sanitizer_platform_limits_posix.h | 9 +++ compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 9 ++- 7 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 compiler-rt/lib/msan/lit_tests/Linux/glob_altdirfunc.cc diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index a8e260bacaa9..bdcc4f729d68 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -102,6 +102,9 @@ using namespace __asan; // NOLINT DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) +#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \ + do { \ + } while (false) #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ ASAN_WRITE_RANGE(ptr, size) #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) diff --git a/compiler-rt/lib/msan/lit_tests/Linux/glob_altdirfunc.cc b/compiler-rt/lib/msan/lit_tests/Linux/glob_altdirfunc.cc new file mode 100644 index 000000000000..45a3818d17e9 --- /dev/null +++ b/compiler-rt/lib/msan/lit_tests/Linux/glob_altdirfunc.cc @@ -0,0 +1,77 @@ +// RUN: %clangxx_msan -m64 -O0 %s -o %t && %t %p 2>&1 | FileCheck %s +// RUN: %clangxx_msan -m64 -O3 %s -o %t && %t %p 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +static void my_gl_closedir(void *dir) { + if (!dir) + exit(1); + closedir((DIR *)dir); +} + +static struct dirent *my_gl_readdir(void *dir) { + if (!dir) + exit(1); + struct dirent *d = readdir((DIR *)dir); + if (d) __msan_poison(d, d->d_reclen); // hehe + return d; +} + +static void *my_gl_opendir(const char *s) { + assert(__msan_test_shadow(s, strlen(s) + 1) == (size_t)-1); + return opendir(s); +} + +static int my_gl_lstat(const char *s, struct stat *st) { + assert(__msan_test_shadow(s, strlen(s) + 1) == (size_t)-1); + if (!st) + exit(1); + return lstat(s, st); +} + +static int my_gl_stat(const char *s, struct stat *st) { + assert(__msan_test_shadow(s, strlen(s) + 1) == (size_t)-1); + if (!st) + exit(1); + return lstat(s, st); +} + +int main(int argc, char *argv[]) { + assert(argc == 2); + char buf[1024]; + snprintf(buf, sizeof(buf), "%s/%s", argv[1], "glob_test_root/*a"); + + glob_t globbuf; + globbuf.gl_closedir = my_gl_closedir; + globbuf.gl_readdir = my_gl_readdir; + globbuf.gl_opendir = my_gl_opendir; + globbuf.gl_lstat = my_gl_lstat; + globbuf.gl_stat = my_gl_stat; + for (int i = 0; i < 10000; ++i) { + int res = glob(buf, GLOB_ALTDIRFUNC | GLOB_MARK, 0, &globbuf); + assert(res == 0); + printf("%d %s\n", errno, strerror(errno)); + assert(globbuf.gl_pathc == 2); + printf("%zu\n", strlen(globbuf.gl_pathv[0])); + printf("%zu\n", strlen(globbuf.gl_pathv[1])); + __msan_poison(globbuf.gl_pathv[0], strlen(globbuf.gl_pathv[0]) + 1); + __msan_poison(globbuf.gl_pathv[1], strlen(globbuf.gl_pathv[1]) + 1); + globfree(&globbuf); + } + + printf("PASS\n"); + // CHECK: PASS + return 0; +} diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc index 13d67b72d873..d5bc84e5555c 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cc +++ b/compiler-rt/lib/msan/msan_interceptors.cc @@ -991,6 +991,8 @@ struct MSanInterceptorContext { CHECK_UNPOISONED_0(x, n); \ } while (0) +#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \ + UnpoisonParam(count) #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ __msan_unpoison(ptr, size) #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 702e6bbd92eb..ca915ba735a0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -751,12 +751,64 @@ static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) { } } +static THREADLOCAL __sanitizer_glob_t* pglob_copy; +static THREADLOCAL void* glob_ctx; + +static void wrapped_gl_closedir(void *dir) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1); + pglob_copy->gl_closedir(dir); +} + +static void *wrapped_gl_readdir(void *dir) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1); + return pglob_copy->gl_readdir(dir); +} + +static void *wrapped_gl_opendir(const char *s) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 1); + COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1); + return pglob_copy->gl_opendir(s); +} + +static int wrapped_gl_lstat(const char *s, void *st) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2); + COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1); + return pglob_copy->gl_lstat(s, st); +} + +static int wrapped_gl_stat(const char *s, void *st) { + COMMON_INTERCEPTOR_UNPOISON_PARAM(glob_ctx, 2); + COMMON_INTERCEPTOR_WRITE_RANGE(glob_ctx, s, REAL(strlen)(s) + 1); + return pglob_copy->gl_stat(s, st); +} + INTERCEPTOR(int, glob, const char *pattern, int flags, int (*errfunc)(const char *epath, int eerrno), __sanitizer_glob_t *pglob) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob); + __sanitizer_glob_t glob_copy = {0, 0, 0, 0, wrapped_gl_closedir, + wrapped_gl_readdir, wrapped_gl_opendir, + wrapped_gl_lstat, wrapped_gl_stat}; + if (flags & glob_altdirfunc) { + Swap(pglob->gl_closedir, glob_copy.gl_closedir); + Swap(pglob->gl_readdir, glob_copy.gl_readdir); + Swap(pglob->gl_opendir, glob_copy.gl_opendir); + Swap(pglob->gl_lstat, glob_copy.gl_lstat); + Swap(pglob->gl_stat, glob_copy.gl_stat); + pglob_copy = &glob_copy; + glob_ctx = ctx; + } int res = REAL(glob)(pattern, flags, errfunc, pglob); + if (flags & glob_altdirfunc) { + Swap(pglob->gl_closedir, glob_copy.gl_closedir); + Swap(pglob->gl_readdir, glob_copy.gl_readdir); + Swap(pglob->gl_opendir, glob_copy.gl_opendir); + Swap(pglob->gl_lstat, glob_copy.gl_lstat); + Swap(pglob->gl_stat, glob_copy.gl_stat); + } + pglob_copy = 0; + glob_ctx = 0; if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob); return res; } 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 abb661109b8e..087628398a27 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -166,6 +166,7 @@ namespace __sanitizer { #if SANITIZER_LINUX && !SANITIZER_ANDROID int glob_nomatch = GLOB_NOMATCH; + int glob_altdirfunc = GLOB_ALTDIRFUNC; #endif #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ @@ -745,9 +746,16 @@ COMPILER_CHECK(IOC_SIZE(0x12345678) == _IOC_SIZE(0x12345678)); #endif #if SANITIZER_LINUX && !SANITIZER_ANDROID -COMPILER_CHECK(sizeof(__sanitizer_glob_t) <= sizeof(glob_t)); +CHECK_TYPE_SIZE(glob_t); CHECK_SIZE_AND_OFFSET(glob_t, gl_pathc); CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv); +CHECK_SIZE_AND_OFFSET(glob_t, gl_offs); +CHECK_SIZE_AND_OFFSET(glob_t, gl_flags); +CHECK_SIZE_AND_OFFSET(glob_t, gl_closedir); +CHECK_SIZE_AND_OFFSET(glob_t, gl_readdir); +CHECK_SIZE_AND_OFFSET(glob_t, gl_opendir); +CHECK_SIZE_AND_OFFSET(glob_t, gl_lstat); +CHECK_SIZE_AND_OFFSET(glob_t, gl_stat); #endif CHECK_TYPE_SIZE(addrinfo); 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 7258526b4129..4e85fbdea9d5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -190,9 +190,18 @@ namespace __sanitizer { struct __sanitizer_glob_t { uptr gl_pathc; char **gl_pathv; + uptr gl_offs; + int gl_flags; + + void (*gl_closedir)(void *); + void *(*gl_readdir)(void *); + void *(*gl_opendir)(const char *); + int (*gl_lstat)(const char *, void *); + int (*gl_stat)(const char *, void *); }; extern int glob_nomatch; + extern int glob_altdirfunc; #endif extern unsigned path_max; diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 7d772263b982..35a582cf22cc 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -1815,9 +1815,12 @@ struct TsanInterceptorContext { // Causes interceptor recursion (glob64() calls lstat64()) #undef SANITIZER_INTERCEPT_GLOB -#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ - MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \ - ((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \ +#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \ + do { \ + } while (false) +#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ + MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \ + ((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \ true) #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \