diff options
-rw-r--r-- | lib/msan/lit_tests/Linux/syscalls.cc | 14 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common_syscalls.inc | 21 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_platform_limits_linux.cc | 22 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_platform_limits_posix.cc | 17 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_platform_limits_posix.h | 36 |
5 files changed, 88 insertions, 22 deletions
diff --git a/lib/msan/lit_tests/Linux/syscalls.cc b/lib/msan/lit_tests/Linux/syscalls.cc index 797832d83..ec308bfe3 100644 --- a/lib/msan/lit_tests/Linux/syscalls.cc +++ b/lib/msan/lit_tests/Linux/syscalls.cc @@ -7,6 +7,7 @@ #include <stdio.h> #include <string.h> +#include <linux/aio_abi.h> #include <sys/ptrace.h> #include <sys/stat.h> @@ -81,6 +82,19 @@ int main(int argc, char *argv[]) { __msan_poison(buf, sizeof(buf)); __sanitizer_syscall_post_ptrace(0, PTRACE_PEEKUSER, kFortyTwo, 0xABCD, buf); assert(__msan_test_shadow(buf, sizeof(buf)) == sizeof(void *)); + + __msan_poison(buf, sizeof(buf)); + struct iocb iocb[2]; + struct iocb *iocbp[2] = { &iocb[0], &iocb[1] }; + memset(iocb, 0, sizeof(iocb)); + iocb[0].aio_lio_opcode = IOCB_CMD_PREAD; + iocb[0].aio_buf = (__u64)buf; + iocb[0].aio_nbytes = kFortyTwo; + 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); return 0; } diff --git a/lib/sanitizer_common/sanitizer_common_syscalls.inc b/lib/sanitizer_common/sanitizer_common_syscalls.inc index 003215552..328363737 100644 --- a/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -1270,15 +1270,30 @@ POST_SYSCALL(io_getevents)(long res, long ctx_id, long min_nr, long nr, } } -PRE_SYSCALL(io_submit)(long, long arg1, void *arg2) {} +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); + } +} -POST_SYSCALL(io_submit)(long res, long, long arg1, void *arg2) {} +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); + } + } +} PRE_SYSCALL(io_cancel)(long ctx_id, void *iocb, void *result) {} POST_SYSCALL(io_cancel)(long res, long ctx_id, void *iocb, void *result) { if (res >= 0) { - if (iocb) POST_WRITE(iocb, struct_iocb_sz); + if (iocb) POST_WRITE(iocb, sizeof(__sanitizer_iocb)); if (result) POST_WRITE(result, struct_io_event_sz); } } diff --git a/lib/sanitizer_common/sanitizer_platform_limits_linux.cc b/lib/sanitizer_common/sanitizer_platform_limits_linux.cc index 9d4eb3495..6efad7675 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_linux.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_linux.cc @@ -19,6 +19,12 @@ #include "sanitizer_platform.h" #if SANITIZER_LINUX +#include "sanitizer_internal_defs.h" +#include "sanitizer_platform_limits_posix.h" + +// For offsetof -> __builtin_offsetof definition. +#include <stddef.h> + // This header seems to contain the definitions of _kernel_ stat* structs. #include <asm/stat.h> #include <linux/aio_abi.h> @@ -37,9 +43,11 @@ namespace __sanitizer { unsigned struct___old_kernel_stat_sz = sizeof(struct __old_kernel_stat); unsigned struct_kernel_stat_sz = sizeof(struct stat); unsigned struct_io_event_sz = sizeof(struct io_event); - unsigned struct_iocb_sz = sizeof(struct iocb); unsigned struct_statfs64_sz = sizeof(struct statfs64); + unsigned iocb_cmd_pread = IOCB_CMD_PREAD; + unsigned iocb_cmd_pwrite = IOCB_CMD_PWRITE; + #ifndef _LP64 unsigned struct_kernel_stat64_sz = sizeof(struct stat64); #else @@ -51,4 +59,16 @@ namespace __sanitizer { #endif } // namespace __sanitizer +CHECK_TYPE_SIZE(iocb); +CHECK_SIZE_AND_OFFSET(iocb, aio_data); +// Skip aio_key, it's weird. +CHECK_SIZE_AND_OFFSET(iocb, aio_lio_opcode); +CHECK_SIZE_AND_OFFSET(iocb, aio_reqprio); +CHECK_SIZE_AND_OFFSET(iocb, aio_fildes); +CHECK_SIZE_AND_OFFSET(iocb, aio_buf); +CHECK_SIZE_AND_OFFSET(iocb, aio_nbytes); +CHECK_SIZE_AND_OFFSET(iocb, aio_offset); +CHECK_SIZE_AND_OFFSET(iocb, aio_flags); +CHECK_SIZE_AND_OFFSET(iocb, aio_resfd); + #endif // SANITIZER_LINUX diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index 22384771a..0e240ab7d 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -764,23 +764,6 @@ namespace __sanitizer { #endif } // namespace __sanitizer -#define CHECK_TYPE_SIZE(TYPE) \ - COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE)) - -#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \ - COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \ - sizeof(((CLASS *) NULL)->MEMBER)); \ - COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \ - offsetof(CLASS, MEMBER)) - -// For sigaction, which is a function and struct at the same time, -// and thus requires explicit "struct" in sizeof() expression. -#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \ - COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *) NULL)->MEMBER) == \ - sizeof(((struct CLASS *) NULL)->MEMBER)); \ - COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \ - offsetof(struct CLASS, MEMBER)) - COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t)); COMPILER_CHECK(sizeof(socklen_t) == sizeof(unsigned)); diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 0fa1b9d28..2da0f7f84 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -52,7 +52,6 @@ namespace __sanitizer { extern unsigned struct_kernel_stat_sz; extern unsigned struct_kernel_stat64_sz; extern unsigned struct_io_event_sz; - extern unsigned struct_iocb_sz; extern unsigned struct_utimbuf_sz; extern unsigned struct_new_utsname_sz; extern unsigned struct_old_utsname_sz; @@ -72,6 +71,24 @@ namespace __sanitizer { const unsigned old_sigset_t_sz = sizeof(unsigned long); const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long); + struct __sanitizer_iocb { + u64 aio_data; + u32 aio_key_or_aio_reserved1; // Simply crazy. + u32 aio_reserved1_or_aio_key; // Luckily, we don't need these. + u16 aio_lio_opcode; + s16 aio_reqprio; + u32 aio_fildes; + u64 aio_buf; + u64 aio_nbytes; + s64 aio_offset; + u64 aio_reserved2; + u32 aio_flags; + u32 aio_resfd; + }; + + extern unsigned iocb_cmd_pread; + extern unsigned iocb_cmd_pwrite; + struct __sanitizer___sysctl_args { int *name; int nlen; @@ -906,5 +923,22 @@ namespace __sanitizer { } // namespace __sanitizer +#define CHECK_TYPE_SIZE(TYPE) \ + COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE)) + +#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \ + COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) == \ + sizeof(((CLASS *) NULL)->MEMBER)); \ + COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \ + offsetof(CLASS, MEMBER)) + +// For sigaction, which is a function and struct at the same time, +// and thus requires explicit "struct" in sizeof() expression. +#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \ + COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *) NULL)->MEMBER) == \ + sizeof(((struct CLASS *) NULL)->MEMBER)); \ + COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \ + offsetof(struct CLASS, MEMBER)) + #endif |