forked from OSchip/llvm-project
[sanitizer] More interceptors.
getpwnam, getpwuid, getpwnam_r, getpwuid_r, clock_getres, clock_gettime, clock_settime, getitimer, setitimer, sigaction (MSan). llvm-svn: 178465
This commit is contained in:
parent
1d021bff28
commit
f8213b4eb3
|
|
@ -824,6 +824,17 @@ INTERCEPTOR(int, getrusage, int who, void *usage) {
|
|||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, sigaction, int signum, const void *act, void *oldact) {
|
||||
ENSURE_MSAN_INITED();
|
||||
// TODO: check that *act is unpoisoned.
|
||||
// That requires intercepting all of sigemptyset, sigfillset, etc.
|
||||
int res = REAL(sigaction)(signum, act, oldact);
|
||||
if (res == 0) {
|
||||
__msan_unpoison(oldact, __sanitizer::struct_sigaction_sz);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
extern "C" int pthread_attr_init(void *attr);
|
||||
extern "C" int pthread_attr_destroy(void *attr);
|
||||
extern "C" int pthread_attr_setstacksize(void *attr, uptr stacksize);
|
||||
|
|
@ -843,6 +854,9 @@ INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
|
|||
int res = REAL(pthread_create)(th, attr, callback, param);
|
||||
if (attr == &myattr)
|
||||
pthread_attr_destroy(&myattr);
|
||||
if (!res) {
|
||||
__msan_unpoison(th, __sanitizer::pthread_t_sz);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1054,6 +1068,7 @@ void InitializeInterceptors() {
|
|||
INTERCEPT_FUNCTION(dladdr);
|
||||
INTERCEPT_FUNCTION(dlopen);
|
||||
INTERCEPT_FUNCTION(getrusage);
|
||||
INTERCEPT_FUNCTION(sigaction);
|
||||
INTERCEPT_FUNCTION(pthread_create);
|
||||
inited = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <sys/vfs.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
# include <emmintrin.h>
|
||||
|
|
@ -849,6 +850,45 @@ TEST(MemorySanitizer, gettimeofday) {
|
|||
EXPECT_NOT_POISONED(tz.tz_dsttime);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, clock_gettime) {
|
||||
struct timespec tp;
|
||||
EXPECT_POISONED(tp.tv_sec);
|
||||
EXPECT_POISONED(tp.tv_nsec);
|
||||
assert(0 == clock_gettime(CLOCK_REALTIME, &tp));
|
||||
EXPECT_NOT_POISONED(tp.tv_sec);
|
||||
EXPECT_NOT_POISONED(tp.tv_nsec);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, getitimer) {
|
||||
struct itimerval it1, it2;
|
||||
int res;
|
||||
EXPECT_POISONED(it1.it_interval.tv_sec);
|
||||
EXPECT_POISONED(it1.it_interval.tv_usec);
|
||||
EXPECT_POISONED(it1.it_value.tv_sec);
|
||||
EXPECT_POISONED(it1.it_value.tv_usec);
|
||||
res = getitimer(ITIMER_VIRTUAL, &it1);
|
||||
assert(!res);
|
||||
EXPECT_NOT_POISONED(it1.it_interval.tv_sec);
|
||||
EXPECT_NOT_POISONED(it1.it_interval.tv_usec);
|
||||
EXPECT_NOT_POISONED(it1.it_value.tv_sec);
|
||||
EXPECT_NOT_POISONED(it1.it_value.tv_usec);
|
||||
|
||||
it1.it_interval.tv_sec = it1.it_value.tv_sec = 10000;
|
||||
it1.it_interval.tv_usec = it1.it_value.tv_usec = 0;
|
||||
|
||||
res = setitimer(ITIMER_VIRTUAL, &it1, &it2);
|
||||
assert(!res);
|
||||
EXPECT_NOT_POISONED(it2.it_interval.tv_sec);
|
||||
EXPECT_NOT_POISONED(it2.it_interval.tv_usec);
|
||||
EXPECT_NOT_POISONED(it2.it_value.tv_sec);
|
||||
EXPECT_NOT_POISONED(it2.it_value.tv_usec);
|
||||
|
||||
// Check that old_value can be 0, and disable the timer.
|
||||
memset(&it1, 0, sizeof(it1));
|
||||
res = setitimer(ITIMER_VIRTUAL, &it1, 0);
|
||||
assert(!res);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, localtime) {
|
||||
time_t t = 123;
|
||||
struct tm *time = localtime(&t);
|
||||
|
|
@ -1434,6 +1474,7 @@ TEST(MemorySanitizer, SimpleThread) {
|
|||
void *p;
|
||||
int res = pthread_create(&t, NULL, SimpleThread_threadfn, NULL);
|
||||
assert(!res);
|
||||
EXPECT_NOT_POISONED(t);
|
||||
res = pthread_join(t, &p);
|
||||
assert(!res);
|
||||
if (!__msan_has_dynamic_component()) // FIXME: intercept pthread_join (?).
|
||||
|
|
@ -1500,6 +1541,40 @@ TEST(MemorySanitizer, gethostname) {
|
|||
EXPECT_NOT_POISONED(strlen(buf));
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, getpwuid) {
|
||||
struct passwd *p = getpwuid(0); // root
|
||||
assert(p);
|
||||
EXPECT_NOT_POISONED(p->pw_name);
|
||||
assert(p->pw_name);
|
||||
EXPECT_NOT_POISONED(p->pw_name[0]);
|
||||
EXPECT_NOT_POISONED(p->pw_uid);
|
||||
assert(p->pw_uid == 0);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, getpwnam_r) {
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdres;
|
||||
char buf[10000];
|
||||
int res = getpwnam_r("root", &pwd, buf, sizeof(buf), &pwdres);
|
||||
assert(!res);
|
||||
EXPECT_NOT_POISONED(pwd.pw_name);
|
||||
assert(pwd.pw_name);
|
||||
EXPECT_NOT_POISONED(pwd.pw_name[0]);
|
||||
EXPECT_NOT_POISONED(pwd.pw_uid);
|
||||
assert(pwd.pw_uid == 0);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, getpwnam_r_positive) {
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdres;
|
||||
char s[5];
|
||||
strncpy(s, "abcd", 5);
|
||||
__msan_poison(s, 5);
|
||||
char buf[10000];
|
||||
int res;
|
||||
EXPECT_UMR(res = getpwnam_r(s, &pwd, buf, sizeof(buf), &pwdres));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static bool applySlt(T value, T shadow) {
|
||||
__msan_partial_poison(&value, &shadow, sizeof(T));
|
||||
|
|
|
|||
|
|
@ -411,6 +411,126 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
|
|||
#define INIT_SCANF
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_GETPWNAM_GETPWUID
|
||||
INTERCEPTOR(void *, getpwnam, const char *name) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
||||
void *res = REAL(getpwnam)(name);
|
||||
if (res != 0)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
|
||||
return res;
|
||||
}
|
||||
INTERCEPTOR(void *, getpwuid, u32 uid) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
|
||||
void *res = REAL(getpwuid)(uid);
|
||||
if (res != 0)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_passwd_sz);
|
||||
return res;
|
||||
}
|
||||
#define INIT_GETPWNAM_GETPWUID \
|
||||
INTERCEPT_FUNCTION(getpwnam); \
|
||||
INTERCEPT_FUNCTION(getpwuid);
|
||||
#else
|
||||
#define INIT_GETPWNAM_GETPWUID
|
||||
#endif
|
||||
|
||||
|
||||
#if SANITIZER_INTERCEPT_GETPWNAM_R_GETPWUID_R
|
||||
INTERCEPTOR(int, getpwnam_r, const char *name, void *pwd,
|
||||
char *buf, SIZE_T buflen, void **result) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
||||
int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
|
||||
if (!res) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
INTERCEPTOR(int, getpwuid_r, u32 uid, void *pwd,
|
||||
char *buf, SIZE_T buflen, void **result) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
|
||||
int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
|
||||
if (!res) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, struct_passwd_sz);
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#define INIT_GETPWNAM_R_GETPWUID_R \
|
||||
INTERCEPT_FUNCTION(getpwnam_r); \
|
||||
INTERCEPT_FUNCTION(getpwuid_r);
|
||||
#else
|
||||
#define INIT_GETPWNAM_R_GETPWUID_R
|
||||
#endif
|
||||
|
||||
|
||||
#if SANITIZER_INTERCEPT_CLOCK_GETTIME
|
||||
INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
|
||||
int res = REAL(clock_getres)(clk_id, tp);
|
||||
if (!res) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
|
||||
int res = REAL(clock_gettime)(clk_id, tp);
|
||||
if (!res) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
|
||||
return REAL(clock_settime)(clk_id, tp);
|
||||
}
|
||||
#define INIT_CLOCK_GETTIME \
|
||||
INTERCEPT_FUNCTION(clock_getres); \
|
||||
INTERCEPT_FUNCTION(clock_gettime); \
|
||||
INTERCEPT_FUNCTION(clock_settime);
|
||||
#else
|
||||
#define INIT_CLOCK_GETTIME
|
||||
#endif
|
||||
|
||||
|
||||
#if SANITIZER_INTERCEPT_GETITIMER
|
||||
INTERCEPTOR(int, getitimer, int which, void *curr_value) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
|
||||
int res = REAL(getitimer)(which, curr_value);
|
||||
if (!res) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerval_sz);
|
||||
int res = REAL(setitimer)(which, new_value, old_value);
|
||||
if (!res && old_value) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#define INIT_GETITIMER \
|
||||
INTERCEPT_FUNCTION(getitimer); \
|
||||
INTERCEPT_FUNCTION(setitimer);
|
||||
#else
|
||||
#define INIT_GETITIMER
|
||||
#endif
|
||||
|
||||
|
||||
#define SANITIZER_COMMON_INTERCEPTORS_INIT \
|
||||
INIT_STRCASECMP; \
|
||||
INIT_STRNCASECMP; \
|
||||
|
|
@ -424,4 +544,8 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
|
|||
INIT_LOCALTIME_AND_FRIENDS; \
|
||||
INIT_SCANF; \
|
||||
INIT_FREXP; \
|
||||
INIT_FREXPF_FREXPL;
|
||||
INIT_FREXPF_FREXPL; \
|
||||
INIT_GETPWNAM_GETPWUID; \
|
||||
INIT_GETPWNAM_R_GETPWUID_R; \
|
||||
INIT_CLOCK_GETTIME; \
|
||||
INIT_GETITIMER;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@
|
|||
|
||||
# define SANITIZER_INTERCEPT_STRCASECMP SI_NOT_WINDOWS
|
||||
|
||||
#if SANITIZER_MAC
|
||||
# define SI_MAC 1
|
||||
#else
|
||||
# define SI_MAC 0
|
||||
#endif
|
||||
|
||||
# define SANITIZER_INTERCEPT_READ SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_PREAD SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS
|
||||
|
|
@ -51,3 +57,8 @@
|
|||
|
||||
# define SANITIZER_INTERCEPT_FREXP 1
|
||||
# define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_NOT_WINDOWS
|
||||
|
||||
# define SANITIZER_INTERCEPT_GETPWNAM_GETPWUID SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_GETPWNAM_R_GETPWUID_R SI_MAC || SI_LINUX_NOT_ANDROID
|
||||
# define SANITIZER_INTERCEPT_CLOCK_GETTIME SI_LINUX
|
||||
# define SANITIZER_INTERCEPT_GETITIMER SI_NOT_WINDOWS
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -40,12 +42,17 @@ namespace __sanitizer {
|
|||
unsigned struct_stat64_sz = sizeof(struct stat64);
|
||||
unsigned struct_rusage_sz = sizeof(struct rusage);
|
||||
unsigned struct_tm_sz = sizeof(struct tm);
|
||||
unsigned struct_passwd_sz = sizeof(struct passwd);
|
||||
unsigned struct_sigaction_sz = sizeof(struct sigaction);
|
||||
unsigned struct_itimerval_sz = sizeof(struct itimerval);
|
||||
unsigned pthread_t_sz = sizeof(pthread_t);
|
||||
|
||||
#if SANITIZER_LINUX
|
||||
unsigned struct_rlimit_sz = sizeof(struct rlimit);
|
||||
unsigned struct_dirent_sz = sizeof(struct dirent);
|
||||
unsigned struct_statfs_sz = sizeof(struct statfs);
|
||||
unsigned struct_epoll_event_sz = sizeof(struct epoll_event);
|
||||
unsigned struct_timespec_sz = sizeof(struct timespec);
|
||||
#endif // __linux__
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
|
|
|||
|
|
@ -23,12 +23,17 @@ namespace __sanitizer {
|
|||
extern unsigned struct_stat64_sz;
|
||||
extern unsigned struct_rusage_sz;
|
||||
extern unsigned struct_tm_sz;
|
||||
extern unsigned struct_passwd_sz;
|
||||
extern unsigned struct_sigaction_sz;
|
||||
extern unsigned struct_itimerval_sz;
|
||||
extern unsigned pthread_t_sz;
|
||||
|
||||
#if SANITIZER_LINUX
|
||||
extern unsigned struct_rlimit_sz;
|
||||
extern unsigned struct_dirent_sz;
|
||||
extern unsigned struct_statfs_sz;
|
||||
extern unsigned struct_epoll_event_sz;
|
||||
extern unsigned struct_timespec_sz;
|
||||
#endif // __linux__
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
|
|
|
|||
|
|
@ -287,6 +287,15 @@ void StatOutput(u64 *stat) {
|
|||
name[StatInt_frexp] = " frexp ";
|
||||
name[StatInt_frexpf] = " frexpf ";
|
||||
name[StatInt_frexpl] = " frexpl ";
|
||||
name[StatInt_getpwnam] = " getpwnam ";
|
||||
name[StatInt_getpwuid] = " getpwuid ";
|
||||
name[StatInt_getpwnam_r] = " getpwnam_r ";
|
||||
name[StatInt_getpwuid_r] = " getpwuid_r ";
|
||||
name[StatInt_clock_getres] = " clock_getres ";
|
||||
name[StatInt_clock_gettime] = " clock_gettime ";
|
||||
name[StatInt_clock_settime] = " clock_settime ";
|
||||
name[StatInt_getitimer] = " getitimer ";
|
||||
name[StatInt_setitimer] = " setitimer ";
|
||||
|
||||
name[StatAnnotation] = "Dynamic annotations ";
|
||||
name[StatAnnotateHappensBefore] = " HappensBefore ";
|
||||
|
|
|
|||
|
|
@ -282,6 +282,15 @@ enum StatType {
|
|||
StatInt_frexp,
|
||||
StatInt_frexpf,
|
||||
StatInt_frexpl,
|
||||
StatInt_getpwnam,
|
||||
StatInt_getpwuid,
|
||||
StatInt_getpwnam_r,
|
||||
StatInt_getpwuid_r,
|
||||
StatInt_clock_getres,
|
||||
StatInt_clock_gettime,
|
||||
StatInt_clock_settime,
|
||||
StatInt_getitimer,
|
||||
StatInt_setitimer,
|
||||
|
||||
// Dynamic annotations.
|
||||
StatAnnotation,
|
||||
|
|
|
|||
Loading…
Reference in New Issue