From 67f5544391c338411b0006bda7dc1b852bbdd4fb Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 11 Oct 2013 14:13:11 +0000 Subject: tsan: catch more races on file descriptors git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@192452 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/sanitizer_common/sanitizer_common_interceptors.inc | 17 +++++++++++++++++ lib/tsan/rtl/tsan_fd.cc | 2 ++ lib/tsan/rtl/tsan_interceptors.cc | 12 ++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index a62ae238d..04c61efdb 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -18,6 +18,7 @@ // COMMON_INTERCEPTOR_INITIALIZE_RANGE // COMMON_INTERCEPTOR_FD_ACQUIRE // COMMON_INTERCEPTOR_FD_RELEASE +// COMMON_INTERCEPTOR_FD_ACCESS // COMMON_INTERCEPTOR_SET_THREAD_NAME // COMMON_INTERCEPTOR_ON_EXIT //===----------------------------------------------------------------------===// @@ -34,6 +35,10 @@ # define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ctx, p, size) #endif +#ifndef COMMON_INTERCEPTOR_FD_ACCESS +# define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) +#endif + #if SANITIZER_INTERCEPT_STRCMP static inline int CharCmpX(unsigned char c1, unsigned char c2) { return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; @@ -185,6 +190,7 @@ static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec, INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); SSIZE_T res = REAL(read)(fd, ptr, count); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); @@ -201,6 +207,7 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) { INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); SSIZE_T res = REAL(pread)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); @@ -217,6 +224,7 @@ INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) { INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); SSIZE_T res = REAL(pread64)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); @@ -234,6 +242,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov, int iovcnt) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); SSIZE_T res = REAL(readv)(fd, iov, iovcnt); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -249,6 +258,7 @@ INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt, OFF_T offset) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -264,6 +274,7 @@ INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt, OFF64_T offset) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -278,6 +289,7 @@ INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt, INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); SSIZE_T res = REAL(write)(fd, ptr, count); @@ -295,6 +307,7 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) { INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset); @@ -312,6 +325,7 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count, OFF64_T offset) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset); @@ -329,6 +343,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov, int iovcnt) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); SSIZE_T res = REAL(writev)(fd, iov, iovcnt); if (res > 0) read_iovec(ctx, iov, iovcnt, res); @@ -344,6 +359,7 @@ INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt, OFF_T offset) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset); if (res > 0) read_iovec(ctx, iov, iovcnt, res); @@ -359,6 +375,7 @@ INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt, OFF64_T offset) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset); if (res > 0) read_iovec(ctx, iov, iovcnt, res); diff --git a/lib/tsan/rtl/tsan_fd.cc b/lib/tsan/rtl/tsan_fd.cc index 332a12d40..703a487a5 100644 --- a/lib/tsan/rtl/tsan_fd.cc +++ b/lib/tsan/rtl/tsan_fd.cc @@ -166,6 +166,8 @@ void FdRelease(ThreadState *thr, uptr pc, int fd) { } void FdAccess(ThreadState *thr, uptr pc, int fd) { + if (fd < 0) + return; DPrintf("#%d: FdAccess(%d)\n", thr->tid, fd); FdDesc *d = fddesc(thr, pc, fd); MemoryRead(thr, pc, (uptr)d, kSizeLog8); diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc index ad7f55914..596664bdf 100644 --- a/lib/tsan/rtl/tsan_interceptors.cc +++ b/lib/tsan/rtl/tsan_interceptors.cc @@ -1524,22 +1524,28 @@ TSAN_INTERCEPTOR(int, pipe2, int *pipefd, int flags) { TSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) { SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags); - if (fd >= 0) + if (fd >= 0) { + FdAccess(thr, pc, fd); FdRelease(thr, pc, fd); + } int res = REAL(send)(fd, buf, len, flags); return res; } TSAN_INTERCEPTOR(long_t, sendmsg, int fd, void *msg, int flags) { SCOPED_TSAN_INTERCEPTOR(sendmsg, fd, msg, flags); - if (fd >= 0) + if (fd >= 0) { + FdAccess(thr, pc, fd); FdRelease(thr, pc, fd); + } int res = REAL(sendmsg)(fd, msg, flags); return res; } TSAN_INTERCEPTOR(long_t, recv, int fd, void *buf, long_t len, int flags) { SCOPED_TSAN_INTERCEPTOR(recv, fd, buf, len, flags); + if (fd >= 0) + FdAccess(thr, pc, fd); int res = REAL(recv)(fd, buf, len, flags); if (res >= 0 && fd >= 0) { FdAcquire(thr, pc, fd); @@ -1901,6 +1907,8 @@ struct TsanInterceptorContext { FdAcquire(((TsanInterceptorContext *) ctx)->thr, pc, fd) #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ FdRelease(((TsanInterceptorContext *) ctx)->thr, pc, fd) +#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) \ + FdAccess(((TsanInterceptorContext *) ctx)->thr, pc, fd) #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ FdSocketAccept(((TsanInterceptorContext *) ctx)->thr, pc, fd, newfd) #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ -- cgit v1.2.1