Skip to content

[compiler-rt][rtsan] process_vm_readv/process_vm_writev interception. #123839

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 22, 2025

Conversation

devnexen
Copy link
Member

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Jan 21, 2025

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: David CARLIER (devnexen)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/123839.diff

2 Files Affected:

  • (modified) compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp (+28-1)
  • (modified) compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp (+26)
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index 2d8ab696835081..112191f52648e7 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -933,7 +933,7 @@ INTERCEPTOR(int, recvmmsg, int socket, struct mmsghdr *message,
 #else
 INTERCEPTOR(int, recvmmsg, int socket, struct mmsghdr *message,
             unsigned int len, int flags, struct timespec *timeout) {
-#endif
+#endif // defined(__GLIBC_MINOR) && __GLIBC_MINOR__ < 21
   __rtsan_notify_intercepted_call("recvmmsg");
   return REAL(recvmmsg)(socket, message, len, flags, timeout);
 }
@@ -1098,6 +1098,30 @@ INTERCEPTOR(int, execve, const char *filename, char *const argv[],
   return REAL(execve)(filename, argv, envp);
 }
 
+#if SANITIZER_INTERCEPT_PROCESS_VM_READV
+INTERCEPTOR(ssize_t, process_vm_readv, const struct iovec *local_iov,
+            unsigned long liovcnt, const struct iovec *remote_iov,
+            unsigned long riovcnt, unsigned long flags) {
+  __rtsan_notify_intercepted_call("process_vm_readv");
+  return REAL(process_vm_readv)(local_iov, liovcnt, remote_iov, riovcnt, flags);
+}
+
+INTERCEPTOR(ssize_t, process_vm_writev, const struct iovec *local_iov,
+            unsigned long liovcnt, const struct iovec *remote_iov,
+            unsigned long riovcnt, unsigned long flags) {
+  __rtsan_notify_intercepted_call("process_vm_writev");
+  return REAL(process_vm_writev)(local_iov, liovcnt, remote_iov, riovcnt,
+                                 flags);
+}
+#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_READV                                 \
+  INTERCEPT_FUNCTION(process_vm_readv)
+#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV                                \
+  INTERCEPT_FUNCTION(process_vm_writev)
+#else
+#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_READV
+#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV
+#endif
+
 // TODO: the `wait` family of functions is an oddity. In testing, if you
 // intercept them, Darwin seemingly ignores them, and linux never returns from
 // the test. Revisit this in the future, but hopefully intercepting fork/exec is
@@ -1277,6 +1301,9 @@ void __rtsan::InitializeInterceptors() {
   INTERCEPT_FUNCTION(fork);
   INTERCEPT_FUNCTION(execve);
 
+  RTSAN_MAYBE_INTERCEPT_PROCESS_VM_READV;
+  RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV;
+
   INTERCEPT_FUNCTION(syscall);
 }
 
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 c858a5a771fe45..b4b3cc1e39eea1 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -657,6 +657,32 @@ TEST(TestRtsanInterceptors, UmaskDiesWhenRealtime) {
   ExpectNonRealtimeSurvival(Func);
 }
 
+#if SANITIZER_INTERCEPT_PROCESS_VM_READV
+TEST(TestRtsanInterceptors, ProcessVmReadvDiesWhenRealtime) {
+  char stack[1024];
+  int p;
+  iovec lcl{&stack, sizeof(stack)};
+  iovec rmt{&p, sizeof(p)};
+  auto Func = [&lcl, &rmt]() {
+    process_vm_readv(0, &lcl, 1, &rmt, 1, 0);
+  };
+  ExpectRealtimeDeath(Func, "process_vm_readv");
+  ExpectNonRealtimeSurvival(Func);
+}
+
+TEST(TestRtsanInterceptors, ProcessVmWritevDiesWhenRealtime) {
+  char stack[1024];
+  int p;
+  iovec lcl{&p, sizeof(p)};
+  iovec rmt{&stack, sizeof(stack)};
+  auto Func = [&lcl, &rmt]() {
+    process_vm_writev(0, &lcl, 1, &rmt, 1, 0);
+  };
+  ExpectRealtimeDeath(Func, "process_vm_writev");
+  ExpectNonRealtimeSurvival(Func);
+}
+#endif
+
 class RtsanDirectoryTest : public ::testing::Test {
 protected:
   void SetUp() override {

Copy link

github-actions bot commented Jan 21, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@devnexen devnexen force-pushed the rtsan_process_vm_linux branch from 9bb53dd to eb69bc9 Compare January 21, 2025 23:00
@devnexen devnexen merged commit 8fad58a into llvm:main Jan 22, 2025
7 checks passed
@kongy
Copy link
Collaborator

kongy commented Jan 22, 2025

This breaks our build:

llvm-project/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp:1102:22: error: conflicting types for 'process_vm_readv'
 1102 | INTERCEPTOR(ssize_t, process_vm_readv, const struct iovec *local_iov,
      |                      ^
prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/sysroot/usr/include/x86_64-linux-gnu/bits/uio.h:59:16: note: previous declaration is here
   59 | extern ssize_t process_vm_readv (pid_t __pid, const struct iovec *__lvec,
      |                ^

Looks like it is missing the pid argument?

@devnexen
Copy link
Member Author

Ok fixing.

devnexen added a commit to devnexen/llvm-project that referenced this pull request Jan 22, 2025
kongy pushed a commit that referenced this pull request Jan 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants