[sanitizer] Add syscall handlers for sigaction and rt_sigaction.

llvm-svn: 273746
This commit is contained in:
Evgeniy Stepanov
2016-06-24 23:09:44 +00:00
parent c66a06ad0e
commit c8679985ed
3 changed files with 92 additions and 5 deletions

View File

@@ -1835,6 +1835,17 @@
__sanitizer_syscall_pre_impl_vfork()
#define __sanitizer_syscall_post_vfork(res) \
__sanitizer_syscall_post_impl_vfork(res)
#define __sanitizer_syscall_pre_sigaction(signum, act, oldact) \
__sanitizer_syscall_pre_impl_sigaction((long)signum, (long)act, (long)oldact)
#define __sanitizer_syscall_post_sigaction(res, signum, act, oldact) \
__sanitizer_syscall_post_impl_sigaction(res, (long)signum, (long)act, \
(long)oldact)
#define __sanitizer_syscall_pre_rt_sigaction(signum, act, oldact, sz) \
__sanitizer_syscall_pre_impl_rt_sigaction((long)signum, (long)act, \
(long)oldact, (long)sz)
#define __sanitizer_syscall_post_rt_sigaction(res, signum, act, oldact, sz) \
__sanitizer_syscall_post_impl_rt_sigaction(res, (long)signum, (long)act, \
(long)oldact, (long)sz)
// And now a few syscalls we don't handle yet.
#define __sanitizer_syscall_pre_afs_syscall(...)
@@ -1889,7 +1900,6 @@
#define __sanitizer_syscall_pre_query_module(...)
#define __sanitizer_syscall_pre_readahead(...)
#define __sanitizer_syscall_pre_readdir(...)
#define __sanitizer_syscall_pre_rt_sigaction(...)
#define __sanitizer_syscall_pre_rt_sigreturn(...)
#define __sanitizer_syscall_pre_rt_sigsuspend(...)
#define __sanitizer_syscall_pre_security(...)
@@ -1903,7 +1913,6 @@
#define __sanitizer_syscall_pre_setreuid32(...)
#define __sanitizer_syscall_pre_set_thread_area(...)
#define __sanitizer_syscall_pre_setuid32(...)
#define __sanitizer_syscall_pre_sigaction(...)
#define __sanitizer_syscall_pre_sigaltstack(...)
#define __sanitizer_syscall_pre_sigreturn(...)
#define __sanitizer_syscall_pre_sigsuspend(...)
@@ -1971,7 +1980,6 @@
#define __sanitizer_syscall_post_query_module(res, ...)
#define __sanitizer_syscall_post_readahead(res, ...)
#define __sanitizer_syscall_post_readdir(res, ...)
#define __sanitizer_syscall_post_rt_sigaction(res, ...)
#define __sanitizer_syscall_post_rt_sigreturn(res, ...)
#define __sanitizer_syscall_post_rt_sigsuspend(res, ...)
#define __sanitizer_syscall_post_security(res, ...)
@@ -1985,7 +1993,6 @@
#define __sanitizer_syscall_post_setreuid32(res, ...)
#define __sanitizer_syscall_post_set_thread_area(res, ...)
#define __sanitizer_syscall_post_setuid32(res, ...)
#define __sanitizer_syscall_post_sigaction(res, ...)
#define __sanitizer_syscall_post_sigaltstack(res, ...)
#define __sanitizer_syscall_post_sigreturn(res, ...)
#define __sanitizer_syscall_post_sigsuspend(res, ...)
@@ -3062,7 +3069,13 @@ void __sanitizer_syscall_pre_impl_fork();
void __sanitizer_syscall_post_impl_fork(long res);
void __sanitizer_syscall_pre_impl_vfork();
void __sanitizer_syscall_post_impl_vfork(long res);
void __sanitizer_syscall_pre_impl_sigaction(long signum, long act, long oldact);
void __sanitizer_syscall_post_impl_sigaction(long res, long signum, long act,
long oldact);
void __sanitizer_syscall_pre_impl_rt_sigaction(long signum, long act,
long oldact, long sz);
void __sanitizer_syscall_post_impl_rt_sigaction(long res, long signum, long act,
long oldact, long sz);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -2840,6 +2840,40 @@ PRE_SYSCALL(vfork)() {
POST_SYSCALL(vfork)(long res) {
COMMON_SYSCALL_POST_FORK(res);
}
PRE_SYSCALL(sigaction)(long signum, const __sanitizer_kernel_sigaction_t *act,
__sanitizer_kernel_sigaction_t *oldact) {
if (act) {
PRE_READ(&act->sigaction, sizeof(act->sigaction));
PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
PRE_READ(&act->sa_mask, sizeof(act->sa_mask));
}
}
POST_SYSCALL(sigaction)(long res, long signum,
const __sanitizer_kernel_sigaction_t *act,
__sanitizer_kernel_sigaction_t *oldact) {
if (res >= 0 && oldact) POST_WRITE(oldact, sizeof(*oldact));
}
PRE_SYSCALL(rt_sigaction)(long signum,
const __sanitizer_kernel_sigaction_t *act,
__sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
if (act) {
PRE_READ(&act->sigaction, sizeof(act->sigaction));
PRE_READ(&act->sa_flags, sizeof(act->sa_flags));
PRE_READ(&act->sa_mask, sz);
}
}
POST_SYSCALL(rt_sigaction)(long res, long signum,
const __sanitizer_kernel_sigaction_t *act,
__sanitizer_kernel_sigaction_t *oldact, SIZE_T sz) {
if (res >= 0 && oldact) {
SIZE_T oldact_sz = ((char *)&oldact->sa_mask) - ((char *)oldact) + sz;
POST_WRITE(oldact, oldact_sz);
}
}
} // extern "C"
#undef PRE_SYSCALL

View File

@@ -0,0 +1,40 @@
// RUN: %clangxx_msan -DPRE1 -O0 %s -o %t && not %run %t 2>&1
// RUN: %clangxx_msan -DPRE2 -O0 %s -o %t && not %run %t 2>&1
// RUN: %clangxx_msan -DPRE3 -O0 %s -o %t && not %run %t 2>&1
// RUN: %clangxx_msan -O0 %s -o %t && %run %t 2>&1
#include <assert.h>
#include <signal.h>
#include <string.h>
#include <sanitizer/linux_syscall_hooks.h>
#include <sanitizer/msan_interface.h>
struct my_kernel_sigaction {
long handler, flags, restorer;
uint64_t mask[20]; // larger than any known platform
};
int main() {
my_kernel_sigaction act = {}, oldact = {};
#if defined(PRE1)
__msan_poison(&act.handler, sizeof(act.handler));
__sanitizer_syscall_pre_rt_sigaction(SIGUSR1, &act, &oldact, 20 * 8);
#elif defined(PRE2)
__msan_poison(&act.flags, sizeof(act.flags));
__sanitizer_syscall_pre_rt_sigaction(SIGUSR1, &act, &oldact, 20 * 8);
#elif defined(PRE3)
__msan_poison(&act.mask, 1);
__sanitizer_syscall_pre_rt_sigaction(SIGUSR1, &act, &oldact, 20 * 8);
#else
// Uninit past the end of the mask is ignored.
__msan_poison(((char *)&act.mask) + 5, 1);
__sanitizer_syscall_pre_rt_sigaction(SIGUSR1, &act, &oldact, 5);
memset(&act, 0, sizeof(act));
__msan_poison(&oldact, sizeof(oldact));
__sanitizer_syscall_post_rt_sigaction(0, SIGUSR1, &act, &oldact, 5);
assert(__msan_test_shadow(&oldact, sizeof(oldact)) == sizeof(long)*3 + 5);
#endif
}