Index: msan/lit_tests/Linux/syscalls.cc =================================================================== --- msan/lit_tests/Linux/syscalls.cc +++ msan/lit_tests/Linux/syscalls.cc @@ -93,8 +93,8 @@ iocb[1].aio_lio_opcode = IOCB_CMD_PREAD; iocb[1].aio_buf = (__u64)(&buf[kFortyTwo]); iocb[1].aio_nbytes = kFortyTwo; - __sanitizer_syscall_post_io_submit(1, 0, 2, &iocbp); - assert(__msan_test_shadow(buf, sizeof(buf)) == kFortyTwo); + __sanitizer_syscall_pre_io_submit(0, 2, &iocbp); + assert(__msan_test_shadow(buf, sizeof(buf)) == 2 * kFortyTwo); __msan_poison(buf, sizeof(buf)); char *p = buf; Index: sanitizer_common/sanitizer_common_syscalls.inc =================================================================== --- sanitizer_common/sanitizer_common_syscalls.inc +++ sanitizer_common/sanitizer_common_syscalls.inc @@ -25,8 +25,16 @@ // COMMON_SYSCALL_POST_WRITE_RANGE // Called in posthook for regions that were written to by the kernel // and are now initialized. +// COMMON_SYSCALL_ACQUIRE(addr) +// Acquire memory visibility from addr. +// COMMON_SYSCALL_RELEASE(addr) +// Release memory visibility to addr. // COMMON_SYSCALL_FD_CLOSE(fd) // Called before closing file descriptor fd. +// COMMON_SYSCALL_FD_ACQUIRE(fd) +// Acquire memory visibility from fd. +// COMMON_SYSCALL_FD_RELEASE(fd) +// Release memory visibility to fd. // COMMON_SYSCALL_PRE_FORK() // Called before fork syscall. // COMMON_SYSCALL_POST_FORK(long res) @@ -48,16 +56,32 @@ #define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s) #define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s) +#ifndef COMMON_SYSCALL_ACQUIRE +# define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr)) +#endif + +#ifndef COMMON_SYSCALL_RELEASE +# define COMMON_SYSCALL_RELEASE(addr) ((void)(addr)) +#endif + #ifndef COMMON_SYSCALL_FD_CLOSE -# define COMMON_SYSCALL_FD_CLOSE(fd) +# define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd)) +#endif + +#ifndef COMMON_SYSCALL_FD_ACQUIRE +# define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd)) +#endif + +#ifndef COMMON_SYSCALL_FD_RELEASE +# define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd)) #endif #ifndef COMMON_SYSCALL_PRE_FORK -# define COMMON_SYSCALL_PRE_FORK() +# define COMMON_SYSCALL_PRE_FORK() {} #endif #ifndef COMMON_SYSCALL_POST_FORK -# define COMMON_SYSCALL_POST_FORK(res) +# define COMMON_SYSCALL_POST_FORK(res) {} #endif // FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such). @@ -1263,44 +1287,61 @@ POST_SYSCALL(io_destroy)(long res, long ctx) {} -PRE_SYSCALL(io_getevents)(long ctx_id, long min_nr, long nr, void *events, - void *timeout) { +PRE_SYSCALL(io_getevents)(long ctx_id, long min_nr, long nr, + __sanitizer_io_event *ioevpp, void *timeout) { if (timeout) PRE_READ(timeout, struct_timespec_sz); } POST_SYSCALL(io_getevents)(long res, long ctx_id, long min_nr, long nr, - void *events, void *timeout) { + __sanitizer_io_event *ioevpp, void *timeout) { if (res >= 0) { - if (events) POST_WRITE(events, res * struct_io_event_sz); + if (ioevpp) POST_WRITE(ioevpp, res * sizeof(*ioevpp)); if (timeout) POST_WRITE(timeout, struct_timespec_sz); } + for (long i = 0; i < res; i++) + COMMON_SYSCALL_ACQUIRE((void*)ioevpp[i].data); } PRE_SYSCALL(io_submit)(long ctx_id, long nr, __sanitizer_iocb **iocbpp) { for (long i = 0; i < nr; ++i) { - if (iocbpp[i]->aio_lio_opcode == iocb_cmd_pwrite && iocbpp[i]->aio_buf && - iocbpp[i]->aio_nbytes) - PRE_READ((void *)iocbpp[i]->aio_buf, iocbpp[i]->aio_nbytes); + uptr op = iocbpp[i]->aio_lio_opcode; + int fd = iocbpp[i]->aio_fildes; + void *data = (void*)iocbpp[i]->aio_data; + void *buf = (void*)iocbpp[i]->aio_buf; + uptr len = (uptr)iocbpp[i]->aio_nbytes; + if (op == iocb_cmd_pwrite && buf && len) { + PRE_READ(buf, len); + } else if (op == iocb_cmd_pread && buf && len) { + POST_WRITE(buf, len); + } else if (op == iocb_cmd_pwritev) { + __sanitizer_iovec *iovec = (__sanitizer_iovec*)iocbpp[i]->aio_buf; + for (uptr v = 0; v < len; v++) + PRE_READ(iovec[i].iov_base, iovec[i].iov_len); + } else if (op == iocb_cmd_preadv) { + __sanitizer_iovec *iovec = (__sanitizer_iovec*)iocbpp[i]->aio_buf; + for (uptr v = 0; v < len; v++) + POST_WRITE(iovec[i].iov_base, iovec[i].iov_len); + } + COMMON_SYSCALL_RELEASE(data); } } POST_SYSCALL(io_submit)(long res, long ctx_id, long nr, - __sanitizer_iocb **iocbpp) { - if (res > 0 && iocbpp) { - for (long i = 0; i < res; ++i) { - if (iocbpp[i]->aio_lio_opcode == iocb_cmd_pread && iocbpp[i]->aio_buf && - iocbpp[i]->aio_nbytes) - POST_WRITE((void *)iocbpp[i]->aio_buf, iocbpp[i]->aio_nbytes); - } - } -} + __sanitizer_iocb **iocbpp) {} -PRE_SYSCALL(io_cancel)(long ctx_id, void *iocb, void *result) {} +PRE_SYSCALL(io_cancel)(long ctx_id, __sanitizer_iocb *iocb, + __sanitizer_io_event *result) { +} -POST_SYSCALL(io_cancel)(long res, long ctx_id, void *iocb, void *result) { - if (res >= 0) { - if (iocb) POST_WRITE(iocb, sizeof(__sanitizer_iocb)); - if (result) POST_WRITE(result, struct_io_event_sz); +POST_SYSCALL(io_cancel)(long res, long ctx_id, __sanitizer_iocb *iocb, + __sanitizer_io_event *result) { + if (res == 0) { + if (result) { + COMMON_SYSCALL_ACQUIRE((void*)result->data); + POST_WRITE(result, sizeof(*result)); + } + if (iocb) + POST_WRITE(iocb, sizeof(*iocb)); } } Index: sanitizer_common/sanitizer_platform_limits_linux.cc =================================================================== --- sanitizer_common/sanitizer_platform_limits_linux.cc +++ sanitizer_common/sanitizer_platform_limits_linux.cc @@ -70,7 +70,11 @@ COMPILER_CHECK(struct_kernel_stat64_sz == sizeof(struct stat64)); #endif -COMPILER_CHECK(struct_io_event_sz == sizeof(struct io_event)); +COMPILER_CHECK(sizeof(__sanitizer_io_event) == sizeof(struct io_event)); +CHECK_SIZE_AND_OFFSET(io_event, data); +CHECK_SIZE_AND_OFFSET(io_event, obj); +CHECK_SIZE_AND_OFFSET(io_event, res); +CHECK_SIZE_AND_OFFSET(io_event, res2); #if !SANITIZER_ANDROID COMPILER_CHECK(sizeof(struct __sanitizer_perf_event_attr) <= Index: sanitizer_common/sanitizer_platform_limits_posix.h =================================================================== --- sanitizer_common/sanitizer_platform_limits_posix.h +++ sanitizer_common/sanitizer_platform_limits_posix.h @@ -70,7 +70,6 @@ const unsigned struct_kernel_stat_sz = 144; const unsigned struct_kernel_stat64_sz = 104; #endif - const unsigned struct_io_event_sz = 32; struct __sanitizer_perf_event_attr { unsigned type; unsigned size; @@ -109,8 +108,17 @@ u64 aio_reserved3; }; + struct __sanitizer_io_event { + u64 data; + u64 obj; + u64 res; + u64 res2; + }; + const unsigned iocb_cmd_pread = 0; const unsigned iocb_cmd_pwrite = 1; + const unsigned iocb_cmd_preadv = 7; + const unsigned iocb_cmd_pwritev = 8; struct __sanitizer___sysctl_args { int *name; Index: tsan/rtl/tsan_interceptors.cc =================================================================== --- tsan/rtl/tsan_interceptors.cc +++ tsan/rtl/tsan_interceptors.cc @@ -1927,10 +1927,33 @@ MemoryAccessRange(thr, pc, p, s, write); } +static void syscall_acquire(uptr pc, uptr addr) { + TSAN_SYSCALL(); + Acquire(thr, pc, addr); + Printf("syscall_acquire(%p)\n", addr); +} + +static void syscall_release(uptr pc, uptr addr) { + TSAN_SYSCALL(); + Printf("syscall_release(%p)\n", addr); + Release(thr, pc, addr); +} + static void syscall_fd_close(uptr pc, int fd) { TSAN_SYSCALL(); - if (fd >= 0) - FdClose(thr, pc, fd); + FdClose(thr, pc, fd); +} + +static USED void syscall_fd_acquire(uptr pc, int fd) { + TSAN_SYSCALL(); + FdAcquire(thr, pc, fd); + Printf("syscall_fd_acquire(%p)\n", fd); +} + +static USED void syscall_fd_release(uptr pc, int fd) { + TSAN_SYSCALL(); + Printf("syscall_fd_release(%p)\n", fd); + FdRelease(thr, pc, fd); } static void syscall_pre_fork(uptr pc) { @@ -1949,23 +1972,40 @@ #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) \ syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), false) + #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \ syscall_access_range(GET_CALLER_PC(), (uptr)(p), (uptr)(s), true) + #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ do { \ (void)(p); \ (void)(s); \ } while (false) + #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ do { \ (void)(p); \ (void)(s); \ } while (false) + +#define COMMON_SYSCALL_ACQUIRE(addr) \ + syscall_acquire(GET_CALLER_PC(), (uptr)(addr)) + +#define COMMON_SYSCALL_RELEASE(addr) \ + syscall_release(GET_CALLER_PC(), (uptr)(addr)) + #define COMMON_SYSCALL_FD_CLOSE(fd) syscall_fd_close(GET_CALLER_PC(), fd) + +#define COMMON_SYSCALL_FD_ACQUIRE(fd) syscall_fd_acquire(GET_CALLER_PC(), fd) + +#define COMMON_SYSCALL_FD_RELEASE(fd) syscall_fd_release(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 {