Index: msan/lit_tests/Linux/syscalls.cc =================================================================== --- msan/lit_tests/Linux/syscalls.cc +++ msan/lit_tests/Linux/syscalls.cc @@ -93,8 +93,9 @@ 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); +printf("XXX=%d\n", (int)__msan_test_shadow(buf, sizeof(buf))); + 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 @@ -27,6 +27,10 @@ // and are now initialized. // 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) @@ -49,15 +53,23 @@ #define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s) #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,43 +1275,53 @@ 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_iocb **iocbpp, 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_iocb **iocbpp, void *timeout) { if (res >= 0) { - if (events) POST_WRITE(events, res * struct_io_event_sz); + if (iocbpp) POST_WRITE(iocbpp, res * struct_io_event_sz); if (timeout) POST_WRITE(timeout, struct_timespec_sz); } + for (long i = 0; i < res; i++) { + if (iocbpp[i]->aio_lio_opcode == iocb_cmd_pwrite || + iocbpp[i]->aio_lio_opcode == iocb_cmd_pread) + COMMON_SYSCALL_FD_ACQUIRE(iocbpp[i]->aio_fildes); + } } 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 *buf = (void*)iocbpp[i]->aio_buf; + uptr len = (uptr)iocbpp[i]->aio_nbytes; + if (buf && len) { + if (op == iocb_cmd_pwrite) + PRE_READ(buf, len); + if (op == iocb_cmd_pread) + POST_WRITE(buf, len); + } + if (op == iocb_cmd_pwrite || op == iocb_cmd_pread) + COMMON_SYSCALL_FD_RELEASE(fd); } } 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, void *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)); +POST_SYSCALL(io_cancel)(long res, long ctx_id, __sanitizer_iocb *iocb, + void *result) { + if (res == 0) { + if (iocb) { + COMMON_SYSCALL_FD_ACQUIRE(iocb->aio_fildes); + POST_WRITE(iocb, sizeof(__sanitizer_iocb)); + } if (result) POST_WRITE(result, struct_io_event_sz); } } Index: tsan/rtl/tsan_interceptors.cc =================================================================== --- tsan/rtl/tsan_interceptors.cc +++ tsan/rtl/tsan_interceptors.cc @@ -1929,8 +1929,17 @@ static void syscall_fd_close(uptr pc, int fd) { TSAN_SYSCALL(); - if (fd >= 0) - FdClose(thr, pc, fd); + FdClose(thr, pc, fd); +} + +static void syscall_fd_acquire(uptr pc, int fd) { + TSAN_SYSCALL(); + FdAcquire(thr, pc, fd); +} + +static void syscall_fd_release(uptr pc, int fd) { + TSAN_SYSCALL(); + FdRelease(thr, pc, fd); } static void syscall_pre_fork(uptr pc) { @@ -1949,23 +1958,34 @@ #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_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 {