[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