[compiler-rt] [compiler-rt][rtsan] fseek api interception. (PR #122163)

David CARLIER via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 10 04:00:22 PST 2025


https://github.com/devnexen updated https://github.com/llvm/llvm-project/pull/122163

>From 3a97637257a8b4caed9417f0b641a22597406541 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Wed, 8 Jan 2025 19:53:58 +0000
Subject: [PATCH 1/3] [compiler-rt][rtsan] fseek api interception.

---
 .../lib/rtsan/rtsan_interceptors_posix.cpp    | 100 ++++++++++++++++++
 .../tests/rtsan_test_interceptors_posix.cpp   |  60 +++++++++++
 2 files changed, 160 insertions(+)

diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index 6a5f4b91d11d7e..565b72329d4fd7 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -376,6 +376,95 @@ INTERCEPTOR(void, setbuffer, FILE *stream, char *buf, int size) {
 #define RTSAN_MAYBE_INTERCEPT_SETBUFFER
 #endif
 
+#if SANITIZER_INTERCEPT_FSEEK
+INTERCEPTOR(int, fgetpos, FILE *stream, fpos_t *pos) {
+  __rtsan_notify_intercepted_call("fgetpos");
+  return REAL(fgetpos)(stream, pos);
+}
+
+INTERCEPTOR(int, fseek, FILE *stream, long offset, int whence) {
+  __rtsan_notify_intercepted_call("fseek");
+  return REAL(fgetpos)(stream, offset, whence);
+}
+
+INTERCEPTOR(int, fseeko, FILE *stream, off_t offset, int whence) {
+  __rtsan_notify_intercepted_call("fseeko");
+  return REAL(fseeko)(stream, offset, whence);
+}
+
+INTERCEPTOR(int, fsetpos, FILE *stream, const fpos_t pos) {
+  __rtsan_notify_intercepted_call("fsetpos");
+  return REAL(fsetpos)(stream, pos);
+}
+
+INTERCEPTOR(long, ftell, FILE *stream) {
+  __rtsan_notify_intercepted_call("ftell");
+  return REAL(ftell)(stream);
+}
+
+INTERCEPTOR(off_t, ftello, FILE *stream) {
+  __rtsan_notify_intercepted_call("ftello");
+  return REAL(ftello)(stream);
+}
+
+#if SANITIZER_LINUX
+INTERCEPTOR(int, fgetpos64, FILE *stream, fpos64_t *pos) {
+  __rtsan_notify_intercepted_call("fgetpos64");
+  return REAL(fgetpos64)(stream, pos);
+}
+
+INTERCEPTOR(int, fseeko64, FILE *stream, off64_t offset, int whence) {
+  __rtsan_notify_intercepted_call("fseeko64");
+  return REAL(fgetpos)(stream, offset, whence);
+}
+
+INTERCEPTOR(int, fsetpos64, FILE *stream, const fpos64_t pos) {
+  __rtsan_notify_intercepted_call("fsetpos64");
+  return REAL(fsetpos64)(stream, pos);
+}
+
+INTERCEPTOR(off64_t, ftello64, FILE *stream) {
+  __rtsan_notify_intercepted_call("ftello64");
+  return REAL(ftello64)(stream);
+}
+#endif
+
+INTERCEPTOR(void, rewind, FILE *stream) {
+  __rtsan_notify_intercepted_call("rewind");
+  return REAL(rewind)(stream);
+}
+#define RTSAN_MAYBE_INTERCEPT_FGETPOS INTERCEPT_FUNCTION(fgetpos)
+#define RTSAN_MAYBE_INTERCEPT_FSEEK INTERCEPT_FUNCTION(fseek)
+#define RTSAN_MAYBE_INTERCEPT_FSEEKO INTERCEPT_FUNCTION(fseeko)
+#define RTSAN_MAYBE_INTERCEPT_FSETPOS INTERCEPT_FUNCTION(fsetpos)
+#define RTSAN_MAYBE_INTERCEPT_FTELL INTERCEPT_FUNCTION(ftell)
+#define RTSAN_MAYBE_INTERCEPT_FTELLO INTERCEPT_FUNCTION(ftello)
+#define RTSAN_MAYBE_INTERCEPT_REWIND INTERCEPT_FUNCTION(rewind)
+#if SANITIZER_LINUX
+#define RTSAN_MAYBE_INTERCEPT_FGETPOS64 INTERCEPT_FUNCTION(fgetpos64)
+#define RTSAN_MAYBE_INTERCEPT_FSEEKO64 INTERCEPT_FUNCTION(fseeko64)
+#define RTSAN_MAYBE_INTERCEPT_FSETPOS64 INTERCEPT_FUNCTION(fsetpos64)
+#define RTSAN_MAYBE_INTERCEPT_FTELLO64 INTERCEPT_FUNCTION(ftello64)
+#else
+#define RTSAN_MAYBE_INTERCEPT_FGETPOS64
+#define RTSAN_MAYBE_INTERCEPT_FSEEKO64
+#define RTSAN_MAYBE_INTERCEPT_FSETPOS64
+#define RTSAN_MAYBE_INTERCEPT_FTELLO64
+#endif
+#else
+#define RTSAN_MAYBE_INTERCEPT_FGETPOS
+#define RTSAN_MAYBE_INTERCEPT_FSEEK
+#define RTSAN_MAYBE_INTERCEPT_FSEEKO
+#define RTSAN_MAYBE_INTERCEPT_FSETPOS
+#define RTSAN_MAYBE_INTERCEPT_FTELL
+#define RTSAN_MAYBE_INTERCEPT_FTELLO
+#define RTSAN_MAYBE_INTERCEPT_REWIND
+#define RTSAN_MAYBE_INTERCEPT_FGETPOS64
+#define RTSAN_MAYBE_INTERCEPT_FSEEKO64
+#define RTSAN_MAYBE_INTERCEPT_FSETPOS64
+#define RTSAN_MAYBE_INTERCEPT_FTELLO64
+#endif
+
 INTERCEPTOR(int, puts, const char *s) {
   __rtsan_notify_intercepted_call("puts");
   return REAL(puts)(s);
@@ -1042,6 +1131,17 @@ void __rtsan::InitializeInterceptors() {
   RTSAN_MAYBE_INTERCEPT_SETVBUF;
   RTSAN_MAYBE_INTERCEPT_SETLINEBUF;
   RTSAN_MAYBE_INTERCEPT_SETBUFFER;
+  RTSAN_MAYBE_INTERCEPT_FGETPOS;
+  RTSAN_MAYBE_INTERCEPT_FSEEK;
+  RTSAN_MAYBE_INTERCEPT_FSEEKO;
+  RTSAN_MAYBE_INTERCEPT_FSETPOS;
+  RTSAN_MAYBE_INTERCEPT_FTELL;
+  RTSAN_MAYBE_INTERCEPT_FTELLO;
+  RTSAN_MAYBE_INTERCEPT_REWIND;
+  RTSAN_MAYBE_INTERCEPT_FGETPOS64;
+  RTSAN_MAYBE_INTERCEPT_FSEEKO64;
+  RTSAN_MAYBE_INTERCEPT_FSETPOS64;
+  RTSAN_MAYBE_INTERCEPT_FTELLO64;
   INTERCEPT_FUNCTION(lseek);
   RTSAN_MAYBE_INTERCEPT_LSEEK64;
   INTERCEPT_FUNCTION(dup);
diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
index 5488d3c7e2056c..b0ea2abf8d2b46 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -453,6 +453,66 @@ TEST_F(RtsanFileTest, SetbufferDieWhenRealtime) {
 }
 #endif
 
+#if SANITIZER_INTERCEPT_FSEEK
+TEST_F(RtsanOpenedFileTest, FgetposDieWhenRealtime) {
+  auto Func = [this]() {
+    int pos = fgetpos(GetOpenFile());
+    ASSERT_THAT(pos, Eq(0));
+  };
+
+  ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fgetpos"));
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST_F(RtsanOpenedFileTest, FseekDieWhenRealtime) {
+  auto Func = [this]() {
+    int ret = fseek(GetOpenFile(), 0, SEEK_CUR);
+    ASSERT_THAT(ret, Eq(0));
+  };
+
+  ExpectRealtimeDeath(Func, "fseek");
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST_F(RtsanOpenedFileTest, FseekoDieWhenRealtime) {
+  auto Func = [this]() {
+    int ret = fseeko(GetOpenFile(), 0, SEEK_CUR);
+    ASSERT_THAT(ret, Eq(0));
+  };
+
+  ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fseeko"));
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST_F(RtsanOpenedFileTest, FtellDieWhenRealtime) {
+  auto Func = [this]() {
+    long ret = ftell(GetOpenFile());
+    ASSERT_THAT(ret, Eq(0));
+  };
+
+  ExpectRealtimeDeath(Func, "ftell");
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST_F(RtsanOpenedFileTest, FtelloDieWhenRealtime) {
+  auto Func = [this]() {
+    off_t ret = ftello(GetOpenFile());
+    ASSERT_THAT(ret, Eq(0));
+  };
+
+  ExpectRealtimeDeath(Func, MAYBE_APPEND_64("ftello"));
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST_F(RtsanOpenedFileTest, RewindDieWhenRealtime) {
+  int end = fseek(GetOpenFile(), 0, SEEK_END);
+  auto Func = [this]() { rewind(GetOpenFile()); };
+
+  ExpectRealtimeDeath(Func, "rewind");
+  ExpectNonRealtimeSurvival(Func);
+}
+#endif
+
 class RtsanOpenedFileTest : public RtsanFileTest {
 protected:
   void SetUp() override {

>From 868e2ee2e65d3745d7912c0f3a7e7826a6334eb7 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Thu, 9 Jan 2025 05:00:14 +0000
Subject: [PATCH 2/3] adding fsetpos(64) test

---
 .../lib/rtsan/tests/rtsan_test_interceptors_posix.cpp  | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
index b0ea2abf8d2b46..f46f62e43027a5 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -464,6 +464,16 @@ TEST_F(RtsanOpenedFileTest, FgetposDieWhenRealtime) {
   ExpectNonRealtimeSurvival(Func);
 }
 
+TEST_F(RtsanOpenedFileTest, FsetposDieWhenRealtime) {
+  auto Func = [this]() {
+    int ret = fsetpos(GetOpenFile(), 0);
+    ASSERT_THAT(ret, Eq(0));
+  };
+
+  ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fsetpos"));
+  ExpectNonRealtimeSurvival(Func);
+}
+
 TEST_F(RtsanOpenedFileTest, FseekDieWhenRealtime) {
   auto Func = [this]() {
     int ret = fseek(GetOpenFile(), 0, SEEK_CUR);

>From 1b0187ae48f468047963abcf2c7faabbfaf947d8 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Fri, 10 Jan 2025 11:19:23 +0000
Subject: [PATCH 3/3] enable fseek api family interception to POSIX system fix
 tests

---
 .../lib/rtsan/rtsan_interceptors_posix.cpp    | 12 ++--
 .../tests/rtsan_test_interceptors_posix.cpp   | 62 ++++++++++---------
 .../sanitizer_platform_interceptors.h         |  2 +-
 .../sanitizer_platform_limits_posix.cpp       |  4 ++
 .../sanitizer_platform_limits_posix.h         |  4 ++
 5 files changed, 48 insertions(+), 36 deletions(-)

diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index 565b72329d4fd7..e3f3d12d7e521b 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -384,7 +384,7 @@ INTERCEPTOR(int, fgetpos, FILE *stream, fpos_t *pos) {
 
 INTERCEPTOR(int, fseek, FILE *stream, long offset, int whence) {
   __rtsan_notify_intercepted_call("fseek");
-  return REAL(fgetpos)(stream, offset, whence);
+  return REAL(fseek)(stream, offset, whence);
 }
 
 INTERCEPTOR(int, fseeko, FILE *stream, off_t offset, int whence) {
@@ -392,7 +392,7 @@ INTERCEPTOR(int, fseeko, FILE *stream, off_t offset, int whence) {
   return REAL(fseeko)(stream, offset, whence);
 }
 
-INTERCEPTOR(int, fsetpos, FILE *stream, const fpos_t pos) {
+INTERCEPTOR(int, fsetpos, FILE *stream, const fpos_t *pos) {
   __rtsan_notify_intercepted_call("fsetpos");
   return REAL(fsetpos)(stream, pos);
 }
@@ -407,7 +407,7 @@ INTERCEPTOR(off_t, ftello, FILE *stream) {
   return REAL(ftello)(stream);
 }
 
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_MUSL
 INTERCEPTOR(int, fgetpos64, FILE *stream, fpos64_t *pos) {
   __rtsan_notify_intercepted_call("fgetpos64");
   return REAL(fgetpos64)(stream, pos);
@@ -415,10 +415,10 @@ INTERCEPTOR(int, fgetpos64, FILE *stream, fpos64_t *pos) {
 
 INTERCEPTOR(int, fseeko64, FILE *stream, off64_t offset, int whence) {
   __rtsan_notify_intercepted_call("fseeko64");
-  return REAL(fgetpos)(stream, offset, whence);
+  return REAL(fseeko64)(stream, offset, whence);
 }
 
-INTERCEPTOR(int, fsetpos64, FILE *stream, const fpos64_t pos) {
+INTERCEPTOR(int, fsetpos64, FILE *stream, const fpos64_t *pos) {
   __rtsan_notify_intercepted_call("fsetpos64");
   return REAL(fsetpos64)(stream, pos);
 }
@@ -440,7 +440,7 @@ INTERCEPTOR(void, rewind, FILE *stream) {
 #define RTSAN_MAYBE_INTERCEPT_FTELL INTERCEPT_FUNCTION(ftell)
 #define RTSAN_MAYBE_INTERCEPT_FTELLO INTERCEPT_FUNCTION(ftello)
 #define RTSAN_MAYBE_INTERCEPT_REWIND INTERCEPT_FUNCTION(rewind)
-#if SANITIZER_LINUX
+#if SANITIZER_LINUX && !SANITIZER_MUSL
 #define RTSAN_MAYBE_INTERCEPT_FGETPOS64 INTERCEPT_FUNCTION(fgetpos64)
 #define RTSAN_MAYBE_INTERCEPT_FSEEKO64 INTERCEPT_FUNCTION(fseeko64)
 #define RTSAN_MAYBE_INTERCEPT_FSETPOS64 INTERCEPT_FUNCTION(fsetpos64)
diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
index f46f62e43027a5..e72b810dd8c3bd 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -453,11 +453,37 @@ TEST_F(RtsanFileTest, SetbufferDieWhenRealtime) {
 }
 #endif
 
+class RtsanOpenedFileTest : public RtsanFileTest {
+protected:
+  void SetUp() override {
+    RtsanFileTest::SetUp();
+    file = fopen(GetTemporaryFilePath(), "w");
+    ASSERT_THAT(file, Ne(nullptr));
+    fd = fileno(file);
+    ASSERT_THAT(fd, Ne(-1));
+  }
+
+  void TearDown() override {
+    if (file != nullptr)
+      fclose(file);
+    RtsanFileTest::TearDown();
+  }
+
+  FILE *GetOpenFile() { return file; }
+
+  int GetOpenFd() { return fd; }
+
+private:
+  FILE *file = nullptr;
+  int fd = -1;
+};
+
 #if SANITIZER_INTERCEPT_FSEEK
 TEST_F(RtsanOpenedFileTest, FgetposDieWhenRealtime) {
   auto Func = [this]() {
-    int pos = fgetpos(GetOpenFile());
-    ASSERT_THAT(pos, Eq(0));
+    fpos_t pos;
+    int ret = fgetpos(GetOpenFile(), &pos);
+    ASSERT_THAT(ret, Eq(0));
   };
 
   ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fgetpos"));
@@ -465,8 +491,11 @@ TEST_F(RtsanOpenedFileTest, FgetposDieWhenRealtime) {
 }
 
 TEST_F(RtsanOpenedFileTest, FsetposDieWhenRealtime) {
-  auto Func = [this]() {
-    int ret = fsetpos(GetOpenFile(), 0);
+  fpos_t pos;
+  int ret = fgetpos(GetOpenFile(), &pos);
+  ASSERT_THAT(ret, Eq(0));
+  auto Func = [this, pos]() {
+    int ret = fsetpos(GetOpenFile(), &pos);
     ASSERT_THAT(ret, Eq(0));
   };
 
@@ -523,31 +552,6 @@ TEST_F(RtsanOpenedFileTest, RewindDieWhenRealtime) {
 }
 #endif
 
-class RtsanOpenedFileTest : public RtsanFileTest {
-protected:
-  void SetUp() override {
-    RtsanFileTest::SetUp();
-    file = fopen(GetTemporaryFilePath(), "w");
-    ASSERT_THAT(file, Ne(nullptr));
-    fd = fileno(file);
-    ASSERT_THAT(fd, Ne(-1));
-  }
-
-  void TearDown() override {
-    if (file != nullptr)
-      fclose(file);
-    RtsanFileTest::TearDown();
-  }
-
-  FILE *GetOpenFile() { return file; }
-
-  int GetOpenFd() { return fd; }
-
-private:
-  FILE *file = nullptr;
-  int fd = -1;
-};
-
 TEST(TestRtsanInterceptors, IoctlDiesWhenRealtime) {
   auto Func = []() { ioctl(0, FIONREAD); };
   ExpectRealtimeDeath(Func, "ioctl");
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 190cad7cf7c3f7..febd233bb1e3c0 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -593,7 +593,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
 #define SANITIZER_INTERCEPT_SHA1 SI_NETBSD
 #define SANITIZER_INTERCEPT_MD4 SI_NETBSD
 #define SANITIZER_INTERCEPT_RMD160 SI_NETBSD
-#define SANITIZER_INTERCEPT_FSEEK (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_FSEEK SI_POSIX
 #define SANITIZER_INTERCEPT_MD2 SI_NETBSD
 #define SANITIZER_INTERCEPT_CDB SI_NETBSD
 #define SANITIZER_INTERCEPT_VIS (SI_NETBSD || SI_FREEBSD)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
index c87d5ef42c9242..ad3fb480bbf895 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -545,6 +545,10 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
   unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req);
 #endif
 
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+  unsigned fpos_t_sz = sizeof(fpos_t);
+#endif
+
   const unsigned long __sanitizer_bufsiz = BUFSIZ;
 
   const unsigned IOCTL_NOT_PRESENT = 0;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index ea0933ca64af1d..2dc9964ff20cbd 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -1091,6 +1091,10 @@ extern unsigned struct_sioc_sg_req_sz;
 extern unsigned struct_sioc_vif_req_sz;
 #endif
 
+#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
+extern unsigned fpos_t_sz;
+#endif
+
 // ioctl request identifiers
 
 // A special value to mark ioctls that are not present on the target platform,



More information about the llvm-commits mailing list