forked from OSchip/llvm-project
[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, 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)
|
||||
|
|
|
|||
|
|
@ -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); \
|
||||
} 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) \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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, \
|
||||
|
|
|
|||
Loading…
Reference in New Issue