diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-06-24 23:09:44 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-06-24 23:09:44 +0000 |
commit | c8679985edff033bfdd2b9285945d571fa7799c1 (patch) | |
tree | 554b93ab8964a25046ef5279d1b9ee271fe86c48 | |
parent | c66a06ad0ec57d4981f06e458292d739eed71475 (diff) | |
download | bcm5719-llvm-c8679985edff033bfdd2b9285945d571fa7799c1.tar.gz bcm5719-llvm-c8679985edff033bfdd2b9285945d571fa7799c1.zip |
[sanitizer] Add syscall handlers for sigaction and rt_sigaction.
llvm-svn: 273746
3 files changed, 92 insertions, 5 deletions
diff --git a/compiler-rt/include/sanitizer/linux_syscall_hooks.h b/compiler-rt/include/sanitizer/linux_syscall_hooks.h index 89867c15190..09f261dd672 100644 --- a/compiler-rt/include/sanitizer/linux_syscall_hooks.h +++ b/compiler-rt/include/sanitizer/linux_syscall_hooks.h @@ -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 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc index 48016f218f3..469c8eb7e14 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -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 diff --git a/compiler-rt/test/msan/Linux/syscalls_sigaction.cc b/compiler-rt/test/msan/Linux/syscalls_sigaction.cc new file mode 100644 index 00000000000..1297fae13d1 --- /dev/null +++ b/compiler-rt/test/msan/Linux/syscalls_sigaction.cc @@ -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 +} |