diff --git a/compiler-rt/include/sanitizer/linux_syscall_hooks.h b/compiler-rt/include/sanitizer/linux_syscall_hooks.h --- a/compiler-rt/include/sanitizer/linux_syscall_hooks.h +++ b/compiler-rt/include/sanitizer/linux_syscall_hooks.h @@ -1845,6 +1845,10 @@ #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) +#define __sanitizer_syscall_pre_sigaltstack(ss, oss) \ + __sanitizer_syscall_pre_impl_sigaltstack((long)ss, (long)oss) +#define __sanitizer_syscall_post_sigaltstack(res, ss, oss) \ + __sanitizer_syscall_post_impl_sigaltstack(res, (long)ss, (long)oss) // And now a few syscalls we don't handle yet. #define __sanitizer_syscall_pre_afs_syscall(...) @@ -1912,7 +1916,6 @@ #define __sanitizer_syscall_pre_setreuid32(...) #define __sanitizer_syscall_pre_set_thread_area(...) #define __sanitizer_syscall_pre_setuid32(...) -#define __sanitizer_syscall_pre_sigaltstack(...) #define __sanitizer_syscall_pre_sigreturn(...) #define __sanitizer_syscall_pre_sigsuspend(...) #define __sanitizer_syscall_pre_stty(...) @@ -1992,7 +1995,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_sigaltstack(res, ...) #define __sanitizer_syscall_post_sigreturn(res, ...) #define __sanitizer_syscall_post_sigsuspend(res, ...) #define __sanitizer_syscall_post_stty(res, ...) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -9731,6 +9731,24 @@ #define INIT_QSORT_R #endif +#if SANITIZER_INTERCEPT_SIGALTSTACK +INTERCEPTOR(int, sigaltstack, void *ss, void *oss) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sigaltstack, ss, oss); + if (ss != nullptr) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, ss, struct_stack_t_sz); + } + int r = REAL(sigaltstack)(ss, oss); + if (r == 0 && oss != nullptr) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oss, struct_stack_t_sz); + } + return r; +} +#define INIT_SIGALTSTACK COMMON_INTERCEPT_FUNCTION(sigaltstack) +#else +#define INIT_SIGALTSTACK +#endif + #include "sanitizer_common_interceptors_netbsd_compat.inc" static void InitializeCommonInterceptors() { @@ -10036,6 +10054,7 @@ INIT_GETENTROPY; INIT_QSORT; INIT_QSORT_R; + INIT_SIGALTSTACK; INIT___PRINTF_CHK; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -2885,6 +2885,23 @@ POST_WRITE(buf, res); } } + +PRE_SYSCALL(sigaltstack)(const void *ss, void *oss) { + if (ss != nullptr) { + PRE_READ(ss, struct_stack_t_sz); + } + if (oss != nullptr) { + PRE_WRITE(oss, struct_stack_t_sz); + } +} + +POST_SYSCALL(sigaltstack)(long res, void *ss, void *oss) { + if (res == 0) { + if (oss != nullptr) { + POST_WRITE(oss, struct_stack_t_sz); + } + } +} } // extern "C" #undef PRE_SYSCALL diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -596,5 +596,6 @@ #define SANITIZER_INTERCEPT_QSORT \ (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS) #define SANITIZER_INTERCEPT_QSORT_R (SI_LINUX && !SI_ANDROID) +#define SANITIZER_INTERCEPT_SIGALTSTACK SI_POSIX #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -47,6 +47,7 @@ extern unsigned struct_tms_sz; extern unsigned struct_itimerspec_sz; extern unsigned struct_sigevent_sz; +extern unsigned struct_stack_t_sz; extern unsigned struct_sched_param_sz; extern unsigned struct_statfs64_sz; extern unsigned struct_regex_sz; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -179,6 +179,7 @@ unsigned struct_group_sz = sizeof(struct group); unsigned siginfo_t_sz = sizeof(siginfo_t); unsigned struct_sigaction_sz = sizeof(struct sigaction); + unsigned struct_stack_t_sz = sizeof(stack_t); unsigned struct_itimerval_sz = sizeof(struct itimerval); unsigned pthread_t_sz = sizeof(pthread_t); unsigned pthread_mutex_t_sz = sizeof(pthread_mutex_t); diff --git a/compiler-rt/test/msan/sigaltstack.cpp b/compiler-rt/test/msan/sigaltstack.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/msan/sigaltstack.cpp @@ -0,0 +1,20 @@ +// RUN: %clangxx_msan -O0 -g %s -o %t && not %run %t +// +#include +#include + +#include + +int main(void) { + stack_t old_ss; + + assert(sigaltstack(nullptr, &old_ss) == 0); + __msan_check_mem_is_initialized(&old_ss, sizeof(stack_t)); + + stack_t ss; + sigaltstack(&ss, nullptr); +// CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value +// CHECK: in main {{.*}}sigaltstack.cpp:15 + + return 0; +}