[sanitizer] Support GLOB_ALTDIRFUNC in glob interceptor.

llvm-svn: 185932
This commit is contained in:
Evgeniy Stepanov 2013-07-09 12:07:59 +00:00
parent ab417699dd
commit faba61a7bc
7 changed files with 158 additions and 4 deletions

View File

@ -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)

View File

@ -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 <assert.h>
#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <sanitizer/msan_interface.h>
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;
}

View File

@ -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) \

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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, \