[sanitizer] Support GLOB_ALTDIRFUNC in glob interceptor.
llvm-svn: 185932
This commit is contained in:
parent
ab417699dd
commit
faba61a7bc
|
|
@ -102,6 +102,9 @@ using namespace __asan; // NOLINT
|
||||||
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
|
DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
|
||||||
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
|
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) \
|
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
|
||||||
ASAN_WRITE_RANGE(ptr, size)
|
ASAN_WRITE_RANGE(ptr, size)
|
||||||
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
|
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -991,6 +991,8 @@ struct MSanInterceptorContext {
|
||||||
CHECK_UNPOISONED_0(x, n); \
|
CHECK_UNPOISONED_0(x, n); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
|
||||||
|
UnpoisonParam(count)
|
||||||
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
|
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
|
||||||
__msan_unpoison(ptr, size)
|
__msan_unpoison(ptr, size)
|
||||||
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
|
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
|
||||||
|
|
|
||||||
|
|
@ -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,
|
INTERCEPTOR(int, glob, const char *pattern, int flags,
|
||||||
int (*errfunc)(const char *epath, int eerrno),
|
int (*errfunc)(const char *epath, int eerrno),
|
||||||
__sanitizer_glob_t *pglob) {
|
__sanitizer_glob_t *pglob) {
|
||||||
void *ctx;
|
void *ctx;
|
||||||
COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
|
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);
|
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);
|
if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ namespace __sanitizer {
|
||||||
|
|
||||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||||
int glob_nomatch = GLOB_NOMATCH;
|
int glob_nomatch = GLOB_NOMATCH;
|
||||||
|
int glob_altdirfunc = GLOB_ALTDIRFUNC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID && \
|
||||||
|
|
@ -745,9 +746,16 @@ COMPILER_CHECK(IOC_SIZE(0x12345678) == _IOC_SIZE(0x12345678));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
#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_pathc);
|
||||||
CHECK_SIZE_AND_OFFSET(glob_t, gl_pathv);
|
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
|
#endif
|
||||||
|
|
||||||
CHECK_TYPE_SIZE(addrinfo);
|
CHECK_TYPE_SIZE(addrinfo);
|
||||||
|
|
|
||||||
|
|
@ -190,9 +190,18 @@ namespace __sanitizer {
|
||||||
struct __sanitizer_glob_t {
|
struct __sanitizer_glob_t {
|
||||||
uptr gl_pathc;
|
uptr gl_pathc;
|
||||||
char **gl_pathv;
|
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_nomatch;
|
||||||
|
extern int glob_altdirfunc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern unsigned path_max;
|
extern unsigned path_max;
|
||||||
|
|
|
||||||
|
|
@ -1815,9 +1815,12 @@ struct TsanInterceptorContext {
|
||||||
// Causes interceptor recursion (glob64() calls lstat64())
|
// Causes interceptor recursion (glob64() calls lstat64())
|
||||||
#undef SANITIZER_INTERCEPT_GLOB
|
#undef SANITIZER_INTERCEPT_GLOB
|
||||||
|
|
||||||
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
|
#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \
|
||||||
MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
|
do { \
|
||||||
((TsanInterceptorContext *) ctx)->pc, (uptr) ptr, size, \
|
} while (false)
|
||||||
|
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
|
||||||
|
MemoryAccessRange(((TsanInterceptorContext *)ctx)->thr, \
|
||||||
|
((TsanInterceptorContext *)ctx)->pc, (uptr)ptr, size, \
|
||||||
true)
|
true)
|
||||||
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
|
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
|
||||||
MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
|
MemoryAccessRange(((TsanInterceptorContext *) ctx)->thr, \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue