[compiler-rt] [rtsan] Intercept various file system functions (PR #118183)

Chris Apple via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 30 11:18:44 PST 2024


https://github.com/cjappl created https://github.com/llvm/llvm-project/pull/118183

Adds interceptors for
* chmod
* fchmod
* mkdir
* rmdir
* umask



>From 7ee4264457374c87f4ba1795fbffdea83b9f01e3 Mon Sep 17 00:00:00 2001
From: Chris Apple <cja-private at pm.me>
Date: Sat, 30 Nov 2024 09:24:21 -0800
Subject: [PATCH] Chmod

---
 .../lib/rtsan/rtsan_interceptors_posix.cpp    | 31 +++++++++++
 .../tests/rtsan_test_interceptors_posix.cpp   | 55 +++++++++++++++++++
 2 files changed, 86 insertions(+)

diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index 5debf13ab9815c..64f9ff082d542c 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -47,6 +47,7 @@ void OSSpinLockLock(volatile OSSpinLock *__lock);
 #include <stdarg.h>
 #include <stdio.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -358,6 +359,31 @@ INTERCEPTOR(int, dup2, int oldfd, int newfd) {
   return REAL(dup2)(oldfd, newfd);
 }
 
+INTERCEPTOR(int, chmod, const char *path, mode_t mode) {
+  __rtsan_notify_intercepted_call("chmod");
+  return REAL(chmod)(path, mode);
+}
+
+INTERCEPTOR(int, fchmod, int fd, mode_t mode) {
+  __rtsan_notify_intercepted_call("fchmod");
+  return REAL(fchmod)(fd, mode);
+}
+
+INTERCEPTOR(int, mkdir, const char *path, mode_t mode) {
+  __rtsan_notify_intercepted_call("mkdir");
+  return REAL(mkdir)(path, mode);
+}
+
+INTERCEPTOR(int, rmdir, const char *path) {
+  __rtsan_notify_intercepted_call("rmdir");
+  return REAL(rmdir)(path);
+}
+
+INTERCEPTOR(mode_t, umask, mode_t cmask) {
+  __rtsan_notify_intercepted_call("umask");
+  return REAL(umask)(cmask);
+}
+
 // Concurrency
 #if SANITIZER_APPLE
 #pragma clang diagnostic push
@@ -818,6 +844,11 @@ void __rtsan::InitializeInterceptors() {
   RTSAN_MAYBE_INTERCEPT_LSEEK64;
   INTERCEPT_FUNCTION(dup);
   INTERCEPT_FUNCTION(dup2);
+  INTERCEPT_FUNCTION(chmod);
+  INTERCEPT_FUNCTION(fchmod);
+  INTERCEPT_FUNCTION(mkdir);
+  INTERCEPT_FUNCTION(rmdir);
+  INTERCEPT_FUNCTION(umask);
   INTERCEPT_FUNCTION(ioctl);
 
 #if SANITIZER_APPLE
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 8551424717de6d..f715b0b11b2885 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -46,6 +46,7 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 
@@ -442,6 +443,60 @@ TEST_F(RtsanOpenedFileTest, Dup2DiesWhenRealtime) {
   ExpectNonRealtimeSurvival(Func);
 }
 
+TEST_F(RtsanFileTest, ChmodDiesWhenRealtime) {
+  auto Func = [this]() { chmod(GetTemporaryFilePath(), 0777); };
+  ExpectRealtimeDeath(Func, "chmod");
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST_F(RtsanOpenedFileTest, FchmodDiesWhenRealtime) {
+  auto Func = [this]() { fchmod(GetOpenFd(), 0777); };
+  ExpectRealtimeDeath(Func, "fchmod");
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsanInterceptors, UmaskDiesWhenRealtime) {
+  auto Func = []() { umask(0); };
+  ExpectRealtimeDeath(Func, "umask");
+  ExpectNonRealtimeSurvival(Func);
+}
+
+class RtsanDirectoryTest : public ::testing::Test {
+protected:
+  void SetUp() override {
+    const ::testing::TestInfo *const test_info =
+        ::testing::UnitTest::GetInstance()->current_test_info();
+    directory_path_ = std::string("/tmp/rtsan_temp_dir_") + test_info->name();
+    RemoveTemporaryDirectory();
+  }
+
+  const char *GetTemporaryDirectoryPath() const {
+    return directory_path_.c_str();
+  }
+
+  void TearDown() override { RemoveTemporaryDirectory(); }
+
+private:
+  void RemoveTemporaryDirectory() const {
+    std::remove(GetTemporaryDirectoryPath());
+  }
+  std::string directory_path_;
+};
+
+TEST_F(RtsanDirectoryTest, MkdirDiesWhenRealtime) {
+  auto Func = [this]() { mkdir(GetTemporaryDirectoryPath(), 0777); };
+  ExpectRealtimeDeath(Func, "mkdir");
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST_F(RtsanDirectoryTest, RmdirDiesWhenRealtime) {
+  // We don't actually create this directory before we try to remove it
+  // Thats OK - we are just making sure the call gets intercepted
+  auto Func = [this]() { rmdir(GetTemporaryDirectoryPath()); };
+  ExpectRealtimeDeath(Func, "rmdir");
+  ExpectNonRealtimeSurvival(Func);
+}
+
 TEST_F(RtsanOpenedFileTest, FreadDiesWhenRealtime) {
   auto Func = [this]() {
     char c{};



More information about the llvm-commits mailing list