-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
[compiler-rt][rtsan] ptrace interception on Linux. #123941
base: main
Are you sure you want to change the base?
Conversation
✅ With the latest revision this PR passed the C/C++ code formatter. |
878e3f5
to
4c1262f
Compare
@llvm/pr-subscribers-compiler-rt-sanitizer Author: David CARLIER (devnexen) ChangesFull diff: https://github.com/llvm/llvm-project/pull/123941.diff 2 Files Affected:
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index 71938d3edba38d..64e3fab8200efc 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -41,6 +41,10 @@ void OSSpinLockLock(volatile OSSpinLock *__lock);
#include <malloc.h>
#endif
+#if SANITIZER_INTERCEPT_PTRACE
+#include <sys/ptrace.h>
+#endif
+
#include <fcntl.h>
#include <poll.h>
#include <pthread.h>
@@ -1161,6 +1165,39 @@ INTERCEPTOR(ssize_t, process_vm_writev, pid_t pid,
#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV
#endif
+#if SANITIZER_INTERCEPT_PTRACE
+#if SANITIZER_MUSL
+INTERCEPTOR(long, ptrace, int request, ...) {
+#else
+INTERCEPTOR(long, ptrace, enum __ptrace_request request, ...) {
+#endif // SANITIZER_MUSL
+ __rtsan_notify_intercepted_call("ptrace");
+ va_list args;
+
+ // A handful of ptrace requests need an additional argument on Linux/sparc
+ // (e.g. PTRACE_READDATA) but we only intercept the standard calls at the
+ // moment. We might need to rework all if rtsan is supported on BSD,
+ // interfaces differ vastly, data is read in word size on Linux vs large
+ // chunks on freebsd and so on ...
+ va_start(args, request);
+ pid_t pid = va_arg(args, pid_t);
+
+ // addr and data types depend on the request, either of these are ignored in
+ // some cases too. using intptr_t to be able to hold accepted ptrace types.
+ using arg_type = intptr_t;
+ static_assert(sizeof(arg_type) >= sizeof(struct ptrace_seekinfo_args *));
+ static_assert(sizeof(arg_type) >= sizeof(int));
+ arg_type addr = va_arg(args, arg_type);
+ arg_type priv = va_arg(args, arg_type);
+ va_end(args);
+
+ return REAL(ptrace)(request, pid, addr, priv);
+}
+#define RTSAN_MAYBE_INTERCEPT_PTRACE INTERCEPT_FUNCTION(ptrace)
+#else
+#define RTSAN_MAYBE_INTERCEPT_PTRACE
+#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
@@ -1347,6 +1384,7 @@ void __rtsan::InitializeInterceptors() {
RTSAN_MAYBE_INTERCEPT_PROCESS_VM_READV;
RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV;
+ RTSAN_MAYBE_INTERCEPT_PTRACE;
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 0a59ae0ea92548..8de6c3f9599368 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -43,6 +43,9 @@
#include <poll.h>
#include <pthread.h>
#include <stdio.h>
+#if SANITIZER_INTERCEPT_PTRACE
+#include <sys/ptrace.h>
+#endif
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
@@ -748,6 +751,14 @@ TEST(TestRtsanInterceptors, ProcessVmWritevDiesWhenRealtime) {
}
#endif
+#if SANITIZER_INTERCEPT_PTRACE
+TEST(TestRtsanInterceptors, PtraceWhenRealtime) {
+ auto Func = []() { ptrace(PTRACE_PEEKUSER, -1, 0, nullptr); };
+ ExpectRealtimeDeath(Func, "ptrace");
+ ExpectNonRealtimeSurvival(Func);
+}
+#endif
+
class RtsanDirectoryTest : public ::testing::Test {
protected:
void SetUp() override {
|
I think this is another one like the scheduling ones - this call is used to debug, do we intercept it or assume that someone using it knows what they are doing? An alternative read could be "People should be notified if they accidentally leave ptrace in, and they will not be using it alongside rtsan". @davidtrevelyan do you think we should intercept this call? I'm on the fence |
@cjappl i lean towards intercepting - remembering that our users care about real-time-unsafe calls from within dependencies as well as from within their own code. I'd say that we have easy-enough escape hatches for people who really want to escape to make the cost of missing a ptrace enough to outweigh the cost of disabling when you really want it :) |
29f37ad
to
a58d30d
Compare
No description provided.