[compiler-rt] 03635b3 - [rtsan][compiler-rt] Add 64 bit file interceptors, test for _FILE_OFFSET_BITS (#108057)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 20 06:13:55 PDT 2024
Author: Chris Apple
Date: 2024-09-20T07:13:52-06:00
New Revision: 03635b3215180f71c81a2ec61008e27f84b09aad
URL: https://github.com/llvm/llvm-project/commit/03635b3215180f71c81a2ec61008e27f84b09aad
DIFF: https://github.com/llvm/llvm-project/commit/03635b3215180f71c81a2ec61008e27f84b09aad.diff
LOG: [rtsan][compiler-rt] Add 64 bit file interceptors, test for _FILE_OFFSET_BITS (#108057)
>From #107988
We were not intercepting the 64 bit versions of these calls, leading to
tests failing when _FILE_OFFSET_BITS = 64.
Added:
Modified:
compiler-rt/lib/rtsan/rtsan_interceptors.cpp
compiler-rt/lib/rtsan/tests/CMakeLists.txt
compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors.cpp
index 409e27c3ad3234..344c753d8fe706 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors.cpp
@@ -73,6 +73,25 @@ INTERCEPTOR(int, open, const char *path, int oflag, ...) {
return result;
}
+#if SANITIZER_INTERCEPT_OPEN64
+INTERCEPTOR(int, open64, const char *path, int oflag, ...) {
+ // TODO Establish whether we should intercept here if the flag contains
+ // O_NONBLOCK
+ __rtsan_expect_not_realtime("open64");
+
+ va_list args;
+ va_start(args, oflag);
+ const mode_t mode = va_arg(args, int);
+ va_end(args);
+
+ const int result = REAL(open64)(path, oflag, mode);
+ return result;
+}
+#define RTSAN_MAYBE_INTERCEPT_OPEN64 INTERCEPT_FUNCTION(open64)
+#else
+#define RTSAN_MAYBE_INTERCEPT_OPEN64
+#endif // SANITIZER_INTERCEPT_OPEN64
+
INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {
// TODO Establish whether we should intercept here if the flag contains
// O_NONBLOCK
@@ -87,6 +106,25 @@ INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {
return result;
}
+#if SANITIZER_INTERCEPT_OPENAT64
+INTERCEPTOR(int, openat64, int fd, const char *path, int oflag, ...) {
+ // TODO Establish whether we should intercept here if the flag contains
+ // O_NONBLOCK
+ __rtsan_expect_not_realtime("openat64");
+
+ va_list args;
+ va_start(args, oflag);
+ mode_t mode = va_arg(args, int);
+ va_end(args);
+
+ const int result = REAL(openat64)(fd, path, oflag, mode);
+ return result;
+}
+#define RTSAN_MAYBE_INTERCEPT_OPENAT64 INTERCEPT_FUNCTION(openat64)
+#else
+#define RTSAN_MAYBE_INTERCEPT_OPENAT64
+#endif // SANITIZER_INTERCEPT_OPENAT64
+
INTERCEPTOR(int, creat, const char *path, mode_t mode) {
// TODO Establish whether we should intercept here if the flag contains
// O_NONBLOCK
@@ -95,6 +133,19 @@ INTERCEPTOR(int, creat, const char *path, mode_t mode) {
return result;
}
+#if SANITIZER_INTERCEPT_CREAT64
+INTERCEPTOR(int, creat64, const char *path, mode_t mode) {
+ // TODO Establish whether we should intercept here if the flag contains
+ // O_NONBLOCK
+ __rtsan_expect_not_realtime("creat64");
+ const int result = REAL(creat64)(path, mode);
+ return result;
+}
+#define RTSAN_MAYBE_INTERCEPT_CREAT64 INTERCEPT_FUNCTION(creat64)
+#else
+#define RTSAN_MAYBE_INTERCEPT_CREAT64
+#endif // SANITIZER_INTERCEPT_CREAT64
+
INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {
__rtsan_expect_not_realtime("fcntl");
@@ -116,6 +167,32 @@ INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {
return result;
}
+#if SANITIZER_INTERCEPT_FCNTL64
+INTERCEPTOR(int, fcntl64, int filedes, int cmd, ...) {
+ __rtsan_expect_not_realtime("fcntl64");
+
+ va_list args;
+ va_start(args, cmd);
+
+ // Following precedent here. The linux source (fcntl.c, do_fcntl) accepts the
+ // final argument in a variable that will hold the largest of the possible
+ // argument types (pointers and ints are typical in fcntl) It is then assumed
+ // that the implementation of fcntl will cast it properly depending on cmd.
+ //
+ // This is also similar to what is done in
+ // sanitizer_common/sanitizer_common_syscalls.inc
+ const unsigned long arg = va_arg(args, unsigned long);
+ int result = REAL(fcntl64)(filedes, cmd, arg);
+
+ va_end(args);
+
+ return result;
+}
+#define RTSAN_MAYBE_INTERCEPT_FCNTL64 INTERCEPT_FUNCTION(fcntl64)
+#else
+#define RTSAN_MAYBE_INTERCEPT_FCNTL64
+#endif // SANITIZER_INTERCEPT_FCNTL64
+
INTERCEPTOR(int, close, int filedes) {
__rtsan_expect_not_realtime("close");
return REAL(close)(filedes);
@@ -126,6 +203,16 @@ INTERCEPTOR(FILE *, fopen, const char *path, const char *mode) {
return REAL(fopen)(path, mode);
}
+#if SANITIZER_INTERCEPT_FOPEN64
+INTERCEPTOR(FILE *, fopen64, const char *path, const char *mode) {
+ __rtsan_expect_not_realtime("fopen64");
+ return REAL(fopen64)(path, mode);
+}
+#define RTSAN_MAYBE_INTERCEPT_FOPEN64 INTERCEPT_FUNCTION(fopen64)
+#else
+#define RTSAN_MAYBE_INTERCEPT_FOPEN64
+#endif // SANITIZER_INTERCEPT_FOPEN64
+
INTERCEPTOR(size_t, fread, void *ptr, size_t size, size_t nitems,
FILE *stream) {
__rtsan_expect_not_realtime("fread");
@@ -169,6 +256,16 @@ INTERCEPTOR(ssize_t, pread, int fd, void *buf, size_t count, off_t offset) {
return REAL(pread)(fd, buf, count, offset);
}
+#if SANITIZER_INTERCEPT_PREAD64
+INTERCEPTOR(ssize_t, pread64, int fd, void *buf, size_t count, off_t offset) {
+ __rtsan_expect_not_realtime("pread64");
+ return REAL(pread64)(fd, buf, count, offset);
+}
+#define RTSAN_MAYBE_INTERCEPT_PREAD64 INTERCEPT_FUNCTION(pread64)
+#else
+#define RTSAN_MAYBE_INTERCEPT_PREAD64
+#endif // SANITIZER_INTERCEPT_PREAD64
+
INTERCEPTOR(ssize_t, readv, int fd, const struct iovec *iov, int iovcnt) {
__rtsan_expect_not_realtime("readv");
return REAL(readv)(fd, iov, iovcnt);
@@ -180,6 +277,17 @@ INTERCEPTOR(ssize_t, pwrite, int fd, const void *buf, size_t count,
return REAL(pwrite)(fd, buf, count, offset);
}
+#if SANITIZER_INTERCEPT_PWRITE64
+INTERCEPTOR(ssize_t, pwrite64, int fd, const void *buf, size_t count,
+ off_t offset) {
+ __rtsan_expect_not_realtime("pwrite64");
+ return REAL(pwrite64)(fd, buf, count, offset);
+}
+#define RTSAN_MAYBE_INTERCEPT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
+#else
+#define RTSAN_MAYBE_INTERCEPT_PWRITE64
+#endif // SANITIZER_INTERCEPT_PWRITE64
+
INTERCEPTOR(ssize_t, writev, int fd, const struct iovec *iov, int iovcnt) {
__rtsan_expect_not_realtime("writev");
return REAL(writev)(fd, iov, iovcnt);
@@ -420,20 +528,27 @@ void __rtsan::InitializeInterceptors() {
#endif
INTERCEPT_FUNCTION(open);
+ RTSAN_MAYBE_INTERCEPT_OPEN64;
INTERCEPT_FUNCTION(openat);
+ RTSAN_MAYBE_INTERCEPT_OPENAT64;
INTERCEPT_FUNCTION(close);
INTERCEPT_FUNCTION(fopen);
+ RTSAN_MAYBE_INTERCEPT_FOPEN64;
INTERCEPT_FUNCTION(fread);
INTERCEPT_FUNCTION(read);
INTERCEPT_FUNCTION(write);
INTERCEPT_FUNCTION(pread);
+ RTSAN_MAYBE_INTERCEPT_PREAD64;
INTERCEPT_FUNCTION(readv);
INTERCEPT_FUNCTION(pwrite);
+ RTSAN_MAYBE_INTERCEPT_PWRITE64;
INTERCEPT_FUNCTION(writev);
INTERCEPT_FUNCTION(fwrite);
INTERCEPT_FUNCTION(fclose);
INTERCEPT_FUNCTION(fcntl);
+ RTSAN_MAYBE_INTERCEPT_FCNTL64;
INTERCEPT_FUNCTION(creat);
+ RTSAN_MAYBE_INTERCEPT_CREAT64;
INTERCEPT_FUNCTION(puts);
INTERCEPT_FUNCTION(fputs);
diff --git a/compiler-rt/lib/rtsan/tests/CMakeLists.txt b/compiler-rt/lib/rtsan/tests/CMakeLists.txt
index 5883d33d31895f..0529917bc895ce 100644
--- a/compiler-rt/lib/rtsan/tests/CMakeLists.txt
+++ b/compiler-rt/lib/rtsan/tests/CMakeLists.txt
@@ -76,6 +76,18 @@ foreach(arch ${RTSAN_TEST_ARCH})
CFLAGS ${RTSAN_UNITTEST_CFLAGS} -fsanitize=realtime
LINK_FLAGS ${RTSAN_UNITTEST_LINK_FLAGS} -fsanitize=realtime)
+ check_symbol_exists(__GLIBC__ stdio.h RTSAN_USING_GLIBC)
+ if (RTSAN_USING_GLIBC)
+ set(RtsanTestObjects_FileOffset64)
+ generate_compiler_rt_tests(RtsanTestObjects_FileOffset64
+ RtsanUnitTests "Rtsan-${arch}-FileOffset64-Test" ${arch}
+ COMPILE_DEPS ${RTSAN_UNITTEST_HEADERS}
+ SOURCES ${RTSAN_INST_TEST_SOURCES} ${COMPILER_RT_GOOGLETEST_SOURCES}
+ DEPS rtsan
+ CFLAGS ${RTSAN_UNITTEST_CFLAGS} -D_FILE_OFFSET_BITS=64 -fsanitize=realtime
+ LINK_FLAGS ${RTSAN_UNITTEST_LINK_FLAGS} -fsanitize=realtime)
+ endif()
+
set(RTSAN_TEST_RUNTIME RTRtsanTest.${arch})
if(APPLE)
set(RTSAN_TEST_RUNTIME_OBJECTS
diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp
index 1ef4c66a28de88..2af4e478a01b21 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp
@@ -37,6 +37,24 @@
#include <sys/socket.h>
#include <sys/uio.h>
+#if _FILE_OFFSET_BITS == 64 && SANITIZER_GLIBC
+const char *const kCreatFunctionName = "creat64";
+const char *const kFcntlFunctionName = "fcntl64";
+const char *const kFopenFunctionName = "fopen64";
+const char *const kOpenAtFunctionName = "openat64";
+const char *const kOpenFunctionName = "open64";
+const char *const kPreadFunctionName = "pread64";
+const char *const kPwriteFunctionName = "pwrite64";
+#else
+const char *const kCreatFunctionName = "creat";
+const char *const kFcntlFunctionName = "fcntl";
+const char *const kFopenFunctionName = "fopen";
+const char *const kOpenAtFunctionName = "openat";
+const char *const kOpenFunctionName = "open";
+const char *const kPreadFunctionName = "pread";
+const char *const kPwriteFunctionName = "pwrite";
+#endif
+
using namespace testing;
using namespace rtsan_testing;
using namespace std::chrono_literals;
@@ -183,13 +201,13 @@ TEST(TestRtsanInterceptors, NanosleepDiesWhenRealtime) {
TEST_F(RtsanFileTest, OpenDiesWhenRealtime) {
auto func = [this]() { open(GetTemporaryFilePath(), O_RDONLY); };
- ExpectRealtimeDeath(func, "open");
+ ExpectRealtimeDeath(func, kOpenFunctionName);
ExpectNonRealtimeSurvival(func);
}
TEST_F(RtsanFileTest, OpenatDiesWhenRealtime) {
auto func = [this]() { openat(0, GetTemporaryFilePath(), O_RDONLY); };
- ExpectRealtimeDeath(func, "openat");
+ ExpectRealtimeDeath(func, kOpenAtFunctionName);
ExpectNonRealtimeSurvival(func);
}
@@ -214,13 +232,13 @@ TEST_F(RtsanFileTest, OpenCreatesFileWithProperMode) {
TEST_F(RtsanFileTest, CreatDiesWhenRealtime) {
auto func = [this]() { creat(GetTemporaryFilePath(), S_IWOTH | S_IROTH); };
- ExpectRealtimeDeath(func, "creat");
+ ExpectRealtimeDeath(func, kCreatFunctionName);
ExpectNonRealtimeSurvival(func);
}
TEST(TestRtsanInterceptors, FcntlDiesWhenRealtime) {
auto func = []() { fcntl(0, F_GETFL); };
- ExpectRealtimeDeath(func, "fcntl");
+ ExpectRealtimeDeath(func, kFcntlFunctionName);
ExpectNonRealtimeSurvival(func);
}
@@ -239,7 +257,7 @@ TEST_F(RtsanFileTest, FcntlFlockDiesWhenRealtime) {
ASSERT_THAT(fcntl(fd, F_GETLK, &lock), Eq(0));
ASSERT_THAT(lock.l_type, F_UNLCK);
};
- ExpectRealtimeDeath(func, "fcntl");
+ ExpectRealtimeDeath(func, kFcntlFunctionName);
ExpectNonRealtimeSurvival(func);
close(fd);
@@ -261,7 +279,7 @@ TEST_F(RtsanFileTest, FcntlSetFdDiesWhenRealtime) {
ASSERT_THAT(fcntl(fd, F_GETFD), Eq(old_flags));
};
- ExpectRealtimeDeath(func, "fcntl");
+ ExpectRealtimeDeath(func, kFcntlFunctionName);
ExpectNonRealtimeSurvival(func);
close(fd);
@@ -278,7 +296,8 @@ TEST_F(RtsanFileTest, FopenDiesWhenRealtime) {
auto fd = fopen(GetTemporaryFilePath(), "w");
EXPECT_THAT(fd, Ne(nullptr));
};
- ExpectRealtimeDeath(func, "fopen");
+
+ ExpectRealtimeDeath(func, kFopenFunctionName);
ExpectNonRealtimeSurvival(func);
}
@@ -366,7 +385,7 @@ TEST_F(RtsanOpenedFileTest, PreadDiesWhenRealtime) {
char c{};
pread(GetOpenFd(), &c, 1, 0);
};
- ExpectRealtimeDeath(Func, "pread");
+ ExpectRealtimeDeath(Func, kPreadFunctionName);
ExpectNonRealtimeSurvival(Func);
}
@@ -385,7 +404,7 @@ TEST_F(RtsanOpenedFileTest, PwriteDiesWhenRealtime) {
char c = 'a';
pwrite(GetOpenFd(), &c, 1, 0);
};
- ExpectRealtimeDeath(Func, "pwrite");
+ ExpectRealtimeDeath(Func, kPwriteFunctionName);
ExpectNonRealtimeSurvival(Func);
}
More information about the llvm-commits
mailing list