From 6c21e11b36bb5ebf625463ca6724cf936ef0dc39 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 21 Sep 2013 20:59:04 +0000 Subject: [PATCH] tsan: intercept fork syscall git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@191144 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/sanitizer/linux_syscall_hooks.h | 16 ++++-- lib/sanitizer_common/sanitizer_common_syscalls.inc | 28 ++++++++++ lib/tsan/rtl/tsan_interceptors.cc | 62 +++++++++++++++------- 3 files changed, 84 insertions(+), 22 deletions(-) diff --git a/include/sanitizer/linux_syscall_hooks.h b/include/sanitizer/linux_syscall_hooks.h index d5dc00b6e..9a38070af 100644 --- a/include/sanitizer/linux_syscall_hooks.h +++ b/include/sanitizer/linux_syscall_hooks.h @@ -1826,6 +1826,14 @@ __sanitizer_syscall_post_impl_process_vm_writev( \ res, (long)(pid), (long)(lvec), (long)(liovcnt), (long)(rvec), \ (long)(riovcnt), (long)(flags)) +#define __sanitizer_syscall_pre_fork() \ + __sanitizer_syscall_pre_impl_fork() +#define __sanitizer_syscall_post_fork(res) \ + __sanitizer_syscall_post_impl_fork(res) +#define __sanitizer_syscall_pre_vfork() \ + __sanitizer_syscall_pre_impl_vfork() +#define __sanitizer_syscall_post_vfork(res) \ + __sanitizer_syscall_post_impl_vfork(res) // And now a few syscalls we don't handle yet. #define __sanitizer_syscall_pre_afs_syscall(...) @@ -1843,7 +1851,6 @@ #define __sanitizer_syscall_pre_fanotify_init(...) #define __sanitizer_syscall_pre_fanotify_mark(...) #define __sanitizer_syscall_pre_fchown32(...) -#define __sanitizer_syscall_pre_fork(...) #define __sanitizer_syscall_pre_ftime(...) #define __sanitizer_syscall_pre_ftruncate64(...) #define __sanitizer_syscall_pre_futex(...) @@ -1907,7 +1914,6 @@ #define __sanitizer_syscall_pre_ugetrlimit(...) #define __sanitizer_syscall_pre_ulimit(...) #define __sanitizer_syscall_pre_umount2(...) -#define __sanitizer_syscall_pre_vfork(...) #define __sanitizer_syscall_pre_vm86(...) #define __sanitizer_syscall_pre_vm86old(...) #define __sanitizer_syscall_pre_vserver(...) @@ -1927,7 +1933,6 @@ #define __sanitizer_syscall_post_fanotify_init(res, ...) #define __sanitizer_syscall_post_fanotify_mark(res, ...) #define __sanitizer_syscall_post_fchown32(res, ...) -#define __sanitizer_syscall_post_fork(res, ...) #define __sanitizer_syscall_post_ftime(res, ...) #define __sanitizer_syscall_post_ftruncate64(res, ...) #define __sanitizer_syscall_post_futex(res, ...) @@ -1991,7 +1996,6 @@ #define __sanitizer_syscall_post_ugetrlimit(res, ...) #define __sanitizer_syscall_post_ulimit(res, ...) #define __sanitizer_syscall_post_umount2(res, ...) -#define __sanitizer_syscall_post_vfork(res, ...) #define __sanitizer_syscall_post_vm86old(res, ...) #define __sanitizer_syscall_post_vm86(res, ...) #define __sanitizer_syscall_post_vserver(res, ...) @@ -3053,6 +3057,10 @@ void __sanitizer_syscall_post_impl_process_vm_writev(long res, long pid, long lvec, long liovcnt, long rvec, long riovcnt, long flags); +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); #ifdef __cplusplus } // extern "C" diff --git a/lib/sanitizer_common/sanitizer_common_syscalls.inc b/lib/sanitizer_common/sanitizer_common_syscalls.inc index 6aa2ecf00..942ffc4c9 100644 --- a/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -27,6 +27,10 @@ // and are now initialized. // COMMON_SYSCALL_FD_CLOSE(fd) // Called before closing file descriptor fd. +// COMMON_SYSCALL_PRE_FORK() +// Called before fork syscall. +// COMMON_SYSCALL_POST_FORK(long res) +// Called after fork syscall. //===----------------------------------------------------------------------===// #include "sanitizer_platform.h" @@ -48,6 +52,14 @@ # define COMMON_SYSCALL_FD_CLOSE(fd) #endif +#ifndef COMMON_SYSCALL_PRE_FORK +# define COMMON_SYSCALL_PRE_FORK() +#endif + +#ifndef COMMON_SYSCALL_POST_FORK +# define COMMON_SYSCALL_POST_FORK(res) +#endif + // FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such). extern "C" { @@ -2694,6 +2706,22 @@ POST_SYSCALL(process_vm_writev)(long res, long pid, if (lvec) kernel_read_iovec(lvec, liovcnt, res); } } + +PRE_SYSCALL(fork)() { + COMMON_SYSCALL_PRE_FORK(); +} + +POST_SYSCALL(fork)(long res) { + COMMON_SYSCALL_POST_FORK(res); +} + +PRE_SYSCALL(vfork)() { + COMMON_SYSCALL_PRE_FORK(); +} + +POST_SYSCALL(vfork)(long res) { + COMMON_SYSCALL_POST_FORK(res); +} } // extern "C" #undef PRE_SYSCALL diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index 34178fd72..0338f5a77 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -1792,7 +1792,6 @@ TSAN_INTERCEPTOR(int, munlockall, void) { TSAN_INTERCEPTOR(int, fork, int fake) { SCOPED_TSAN_INTERCEPTOR(fork, fake); - // It's intercepted merely to process pending signals. int pid = REAL(fork)(fake); if (pid == 0) { // child @@ -1846,28 +1845,51 @@ struct TsanInterceptorContext { #define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name) #include "sanitizer_common/sanitizer_common_interceptors.inc" +#define TSAN_SYSCALL() \ + ThreadState *thr = cur_thread(); \ + ScopedSyscall scoped_syscall(thr) \ +/**/ + +struct ScopedSyscall { + ThreadState *thr; + + explicit ScopedSyscall(ThreadState *thr) + : thr(thr) { + if (thr->in_rtl == 0) + Initialize(thr); + thr->in_rtl++; + } + + ~ScopedSyscall() { + thr->in_rtl--; + if (thr->in_rtl == 0) + ProcessPendingSignals(thr); + } +}; + static void syscall_access_range(uptr pc, uptr p, uptr s, bool write) { - ThreadState *thr = cur_thread(); - if (thr->in_rtl == 0) - Initialize(thr); - thr->in_rtl++; + TSAN_SYSCALL(); MemoryAccessRange(thr, pc, p, s, write); - thr->in_rtl--; - if (thr->in_rtl == 0) - ProcessPendingSignals(thr); } static void syscall_fd_close(uptr pc, int fd) { - if (fd < 0) - return; - ThreadState *thr = cur_thread(); - if (thr->in_rtl == 0) - Initialize(thr); - thr->in_rtl++; - FdClose(thr, pc, fd); - thr->in_rtl--; - if (thr->in_rtl == 0) - ProcessPendingSignals(thr); + TSAN_SYSCALL(); + if (fd >= 0) + FdClose(thr, pc, fd); +} + +static void syscall_pre_fork(uptr pc) { + TSAN_SYSCALL(); +} + +static void syscall_post_fork(uptr pc, int res) { + TSAN_SYSCALL(); + if (res == 0) { + // child + FdOnFork(thr, pc); + } else if (res > 0) { + // parent + } } #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \ @@ -1880,6 +1902,10 @@ static void syscall_fd_close(uptr pc, int fd) { do { } while (false) #define COMMON_SYSCALL_FD_CLOSE(fd) \ syscall_fd_close(GET_CALLER_PC(), fd) +#define COMMON_SYSCALL_PRE_FORK() \ + syscall_pre_fork(GET_CALLER_PC()) +#define COMMON_SYSCALL_POST_FORK(res) \ + syscall_post_fork(GET_CALLER_PC(), res) #include "sanitizer_common/sanitizer_common_syscalls.inc" namespace __tsan { -- 2.11.4.GIT