[sanitizer] Simplify sigaction and sigset_t handling.

llvm-svn: 189338
This commit is contained in:
Evgeniy Stepanov 2013-08-27 11:10:04 +00:00
parent b27c4b7cb5
commit a40a058ff1
4 changed files with 54 additions and 37 deletions

View File

@ -909,7 +909,7 @@ static void SignalHandler(int signo) {
static void SignalAction(int signo, void *si, void *uc) {
UnpoisonParam(3);
__msan_unpoison(si, __sanitizer::struct_sigaction_sz);
__msan_unpoison(si, sizeof(__sanitizer_sigaction));
__msan_unpoison(uc, __sanitizer::ucontext_t_sz);
typedef void (*sigaction_cb)(int, void *, void *);
@ -930,21 +930,21 @@ INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
__sanitizer_sigaction new_act;
__sanitizer_sigaction *pnew_act = act ? &new_act : 0;
if (act) {
internal_memcpy(pnew_act, act, __sanitizer::struct_sigaction_sz);
uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(pnew_act);
uptr new_cb =
__sanitizer::__sanitizer_get_sigaction_sa_siginfo(pnew_act) ?
(uptr)SignalAction : (uptr)SignalHandler;
internal_memcpy(pnew_act, act, sizeof(__sanitizer_sigaction));
uptr cb = (uptr)pnew_act->sa_sigaction;
uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
? (uptr)SignalAction
: (uptr)SignalHandler;
if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
sigactions[signo] = cb;
__sanitizer::__sanitizer_set_sigaction_sa_sigaction(pnew_act, new_cb);
pnew_act->sa_sigaction = (void (*)(int, void *, void *))new_cb;
}
}
res = REAL(sigaction)(signo, pnew_act, oldact);
if (res == 0 && oldact) {
uptr cb = __sanitizer::__sanitizer_get_sigaction_sa_sigaction(oldact);
uptr cb = (uptr)oldact->sa_sigaction;
if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
__sanitizer::__sanitizer_set_sigaction_sa_sigaction(oldact, old_cb);
oldact->sa_sigaction = (void (*)(int, void *, void *))old_cb;
}
}
} else {
@ -952,7 +952,7 @@ INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
}
if (res == 0 && oldact) {
__msan_unpoison(oldact, __sanitizer::struct_sigaction_sz);
__msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
}
return res;
}

View File

@ -1976,13 +1976,13 @@ INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
#if SANITIZER_INTERCEPT_PPOLL
INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
void *timeout_ts, void *sigmask) {
void *timeout_ts, __sanitizer_sigset_t *sigmask) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
if (fds && nfds) read_pollfd(ctx, fds, nfds);
if (timeout_ts)
COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, sigset_t_sz);
// FIXME: read sigmask when all of sigemptyset, etc are intercepted.
int res =
COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
if (fds && nfds) write_pollfd(ctx, fds, nfds);

View File

@ -136,26 +136,12 @@ namespace __sanitizer {
uptr sig_ign = (uptr)SIG_IGN;
uptr sig_dfl = (uptr)SIG_DFL;
uptr sa_siginfo = (uptr)SA_SIGINFO;
#if SANITIZER_LINUX
int e_tabsz = (int)E_TABSZ;
#endif
uptr __sanitizer_get_sigaction_sa_sigaction(void *act) {
struct sigaction *a = (struct sigaction *)act;
// Check that sa_sigaction and sa_handler are the same.
CHECK((void *)&(a->sa_sigaction) == (void *)&(a->sa_handler));
return (uptr) a->sa_sigaction;
}
void __sanitizer_set_sigaction_sa_sigaction(void *act, uptr cb) {
struct sigaction *a = (struct sigaction *)act;
a->sa_sigaction = (void (*)(int, siginfo_t *, void *))cb;
}
bool __sanitizer_get_sigaction_sa_siginfo(void *act) {
struct sigaction *a = (struct sigaction *)act;
return a->sa_flags & SA_SIGINFO;
}
int af_inet = (int)AF_INET;
int af_inet6 = (int)AF_INET6;
@ -730,9 +716,15 @@ namespace __sanitizer {
COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \
offsetof(CLASS, MEMBER))
// For sigaction, which is a function and struct at the same time,
// and thus requires explicit "struct" in sizeof() expression.
#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \
COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *) NULL)->MEMBER) == \
sizeof(((struct CLASS *) NULL)->MEMBER)); \
COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \
offsetof(struct CLASS, MEMBER))
COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
COMPILER_CHECK(sizeof(__sanitizer::struct_sigaction_max_sz) >=
sizeof(__sanitizer::struct_sigaction_sz));
COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned));
CHECK_TYPE_SIZE(pthread_key_t);
@ -821,7 +813,19 @@ CHECK_TYPE_SIZE(pollfd);
CHECK_SIZE_AND_OFFSET(pollfd, fd);
CHECK_SIZE_AND_OFFSET(pollfd, events);
CHECK_SIZE_AND_OFFSET(pollfd, revents);
CHECK_TYPE_SIZE(nfds_t);
CHECK_TYPE_SIZE(sigset_t);
COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction));
// Can't write checks for sa_handler and sa_sigaction due to them being
// preprocessor macros.
CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask);
CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags);
#if SANITIZER_LINUX
CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer);
#endif
#endif // SANITIZER_LINUX || SANITIZER_MAC

View File

@ -25,7 +25,6 @@ namespace __sanitizer {
extern unsigned struct_tm_sz;
extern unsigned struct_passwd_sz;
extern unsigned struct_group_sz;
extern unsigned struct_sigaction_sz;
extern unsigned siginfo_t_sz;
extern unsigned struct_itimerval_sz;
extern unsigned pthread_t_sz;
@ -33,7 +32,6 @@ namespace __sanitizer {
extern unsigned timeval_sz;
extern unsigned uid_t_sz;
extern unsigned mbstate_t_sz;
extern unsigned sigset_t_sz;
#if !SANITIZER_ANDROID
extern unsigned ucontext_t_sz;
@ -135,17 +133,32 @@ namespace __sanitizer {
void *align;
};
uptr __sanitizer_get_sigaction_sa_sigaction(void *act);
void __sanitizer_set_sigaction_sa_sigaction(void *act, uptr cb);
bool __sanitizer_get_sigaction_sa_siginfo(void *act);
#if SANITIZER_ANDROID
typedef unsigned long __sanitizer_sigset_t;
#elif SANITIZER_MAC
typedef unsigned __sanitizer_sigset_t;
#elif SANITIZER_LINUX
struct __sanitizer_sigset_t {
// The size is determined by looking at sizeof of real sigset_t on linux.
uptr val[128 / sizeof(uptr)];
};
#endif
const unsigned struct_sigaction_max_sz = 256;
union __sanitizer_sigaction {
char size[struct_sigaction_max_sz]; // NOLINT
struct __sanitizer_sigaction {
union {
void (*sa_handler)(int sig);
void (*sa_sigaction)(int sig, void *siginfo, void *uctx);
};
__sanitizer_sigset_t sa_mask;
int sa_flags;
#if SANITIZER_LINUX
void (*sa_restorer)();
#endif
};
extern uptr sig_ign;
extern uptr sig_dfl;
extern uptr sa_siginfo;
#if SANITIZER_LINUX
extern int e_tabsz;