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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}

Expand Down
22 changes: 22 additions & 0 deletions compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,28 @@ 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 {
Expand Down
Loading