diff --git a/compiler-rt/lib/radsan/radsan_interceptors.cpp b/compiler-rt/lib/radsan/radsan_interceptors.cpp index 53f28f0e98269..83040e36bc653 100644 --- a/compiler-rt/lib/radsan/radsan_interceptors.cpp +++ b/compiler-rt/lib/radsan/radsan_interceptors.cpp @@ -102,6 +102,41 @@ INTERCEPTOR(size_t, fread, void *ptr, size_t size, size_t nitems, return REAL(fread)(ptr, size, nitems, stream); } +INTERCEPTOR(ssize_t, read, int fd, void *buf, size_t count) { + radsan::expectNotRealtime("read"); + return REAL(read)(fd, buf, count); +} + +// intercept write +INTERCEPTOR(ssize_t, write, int fd, const void *buf, size_t count) { + radsan::expectNotRealtime("write"); + return REAL(write)(fd, buf, count); +} + +#if SANITIZER_APPLE +INTERCEPTOR(ssize_t, pread, int fd, void *buf, size_t count, off_t offset) { + radsan::expectNotRealtime("pread"); + return REAL(pread)(fd, buf, count, offset); +} + +INTERCEPTOR(ssize_t, readv, int fd, const struct iovec *iov, int iovcnt) { + radsan::expectNotRealtime("readv"); + return REAL(readv)(fd, iov, iovcnt); +} + +INTERCEPTOR(ssize_t, pwrite, int fd, const void *buf, size_t count, + off_t offset) { + radsan::expectNotRealtime("pwrite"); + return REAL(pwrite)(fd, buf, count, offset); +} + +INTERCEPTOR(ssize_t, writev, int fd, const struct iovec *iov, int iovcnt) { + radsan::expectNotRealtime("writev"); + return REAL(writev)(fd, iov, iovcnt); +} + +#endif // SANITIZER_APPLE + INTERCEPTOR(size_t, fwrite, const void *ptr, size_t size, size_t nitems, FILE *stream) { radsan::expectNotRealtime("fwrite"); @@ -368,6 +403,15 @@ void initialiseInterceptors() { INTERCEPT_FUNCTION(close); INTERCEPT_FUNCTION(fopen); INTERCEPT_FUNCTION(fread); + INTERCEPT_FUNCTION(read); + INTERCEPT_FUNCTION(write); +#if SANITIZER_APPLE + INTERCEPT_FUNCTION(pread); + INTERCEPT_FUNCTION(readv); + INTERCEPT_FUNCTION(pwrite); + INTERCEPT_FUNCTION(writev); +#endif + INTERCEPT_FUNCTION(fwrite); INTERCEPT_FUNCTION(fclose); INTERCEPT_FUNCTION(fcntl); diff --git a/compiler-rt/lib/radsan/tests/radsan_test_interceptors.cpp b/compiler-rt/lib/radsan/tests/radsan_test_interceptors.cpp index 183306a18726d..7fd381c289505 100644 --- a/compiler-rt/lib/radsan/tests/radsan_test_interceptors.cpp +++ b/compiler-rt/lib/radsan/tests/radsan_test_interceptors.cpp @@ -16,6 +16,9 @@ #if SANITIZER_APPLE #include #include +#include +#include +#include #endif #if SANITIZER_INTERCEPT_MEMALIGN || SANITIZER_INTERCEPT_PVALLOC @@ -201,6 +204,7 @@ TEST(TestRadsanInterceptors, closeDiesWhenRealtime) { TEST(TestRadsanInterceptors, fopenDiesWhenRealtime) { auto func = []() { auto fd = fopen(temporary_file_path(), "w"); + // Avoid fopen being dead-code eliminated EXPECT_THAT(fd, Ne(nullptr)); }; expectRealtimeDeath(func, "fopen"); @@ -221,6 +225,83 @@ TEST(TestRadsanInterceptors, freadDiesWhenRealtime) { std::remove(temporary_file_path()); } +class FdFixture : public ::testing::Test { +protected: + int fd = -1; + + void SetUp() override { + fd = open(temporary_file_path(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + ASSERT_TRUE(fd != -1) << "Failed to open file"; + } + + void TearDown() override { + if (fd != -1) + { + close(fd); + remove(temporary_file_path()); + } + } +}; + +TEST_F(FdFixture, readDiesWhenRealtime) { + auto func = [this]() { + char c{}; + read(fd, &c, 1); + }; + expectRealtimeDeath(func, "read"); + expectNonrealtimeSurvival(func); +} + +TEST_F(FdFixture, writeDiesWhenRealtime) { + auto func = [this]() { + char c{}; + write(fd, &c, 1); + }; + expectRealtimeDeath(func, "write"); + expectNonrealtimeSurvival(func); +} + +#if SANITIZER_APPLE +TEST_F(FdFixture, preadDiesWhenRealtime) { + auto func = [this]() { + char c{}; + pread(fd, &c, 1, 0); + }; + expectRealtimeDeath(func, "pread"); + expectNonrealtimeSurvival(func); +} + +TEST_F(FdFixture, readvDiesWhenRealtime) { + auto func = [this]() { + char c{}; + iovec iov = {&c, 1}; + readv(fd, &iov, 1); + }; + expectRealtimeDeath(func, "readv"); + expectNonrealtimeSurvival(func); +} + +TEST_F(FdFixture, pwriteDiesWhenRealtime) { + auto func = [this]() { + char c{}; + pwrite(fd, &c, 1, 0); + }; + expectRealtimeDeath(func, "pwrite"); + expectNonrealtimeSurvival(func); +} + +TEST_F(FdFixture, writevDiesWhenRealtime) { + auto func = [this]() { + char c{}; + iovec iov = {&c, 1}; + writev(fd, &iov, 1); + }; + expectRealtimeDeath(func, "writev"); + expectNonrealtimeSurvival(func); +} + +#endif // SANITIZER_APPLE + TEST(TestRadsanInterceptors, fwriteDiesWhenRealtime) { auto fd = fopen(temporary_file_path(), "w"); ASSERT_NE(nullptr, fd); @@ -233,7 +314,7 @@ TEST(TestRadsanInterceptors, fwriteDiesWhenRealtime) { TEST(TestRadsanInterceptors, fcloseDiesWhenRealtime) { auto fd = fopen(temporary_file_path(), "w"); - EXPECT_THAT(fd, Ne(nullptr)); + EXPECT_THAT(fd, Ne(nullptr)); // Avoids DCE auto func = [fd]() { fclose(fd); }; expectRealtimeDeath(func, "fclose"); expectNonrealtimeSurvival(func); @@ -325,7 +406,8 @@ TEST(TestRadsanInterceptors, osUnfairLockLockDiesWhenRealtime) { expectRealtimeDeath(func, "os_unfair_lock_lock"); expectNonrealtimeSurvival(func); } -#endif + +#endif // SANITIZER_APPLE #if SANITIZER_LINUX TEST(TestRadsanInterceptors, spinLockLockDiesWhenRealtime) {