[compiler-rt] [compiler-rt] intercept ptrace for *BSD. (PR #78044)

David CARLIER via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 13 07:46:13 PST 2024


https://github.com/devnexen created https://github.com/llvm/llvm-project/pull/78044

reusing netbsd naming conventions for freebsd case.

>From d796f5592ab936b3637dd997b02119d6727349e9 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Sat, 13 Jan 2024 15:45:11 +0000
Subject: [PATCH] [compiler-rt] intercept ptrace for *BSD.

reusing netbsd naming conventions for freebsd case.
---
 .../sanitizer_common_interceptors.inc         | 31 +++++++++++++++++++
 .../sanitizer_platform_interceptors.h         |  1 +
 .../sanitizer_platform_limits_freebsd.cpp     |  5 +++
 .../sanitizer_platform_limits_freebsd.h       |  5 +++
 .../TestCases/FreeBSD/ptrace.cpp              | 27 ++++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 compiler-rt/test/sanitizer_common/TestCases/FreeBSD/ptrace.cpp

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 77fa1b4965a7a4..da2ffff2467e11 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -10258,6 +10258,36 @@ INTERCEPTOR(int, cpuset_getaffinity, int level, int which, __int64_t id, SIZE_T
 #define INIT_CPUSET_GETAFFINITY
 #endif
 
+#if SANITIZER_INTERCEPT_PTRACE_BSD
+INTERCEPTOR(int, ptrace, int request, pid_t pid, uptr addr, int data) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
+
+  if (request == ptrace_pt_io) {
+    // for PT_IO requests, data is ignored for both platforms
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, reinterpret_cast<void *>(addr), struct_ptrace_ptrace_io_desc_struct_sz);
+  } else if (request == ptrace_pt_lwpstatus) {
+    if (struct_ptrace_ptrace_lwpinfo_struct_sz != static_cast<u64>(data))
+      VPrintf(2, "Invalid data argument %d for request %d\n", data, request);
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, reinterpret_cast<void *>(addr), struct_ptrace_ptrace_lwpinfo_struct_sz);
+  }
+
+  int res = REAL(ptrace)(request, pid, addr, data);
+
+  if (!res) {
+    if (request == ptrace_pt_io) {
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, reinterpret_cast<void *>(addr), struct_ptrace_ptrace_io_desc_struct_sz);
+    } else if (request == ptrace_pt_lwpstatus) {
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, reinterpret_cast<void *>(addr), struct_ptrace_ptrace_lwpinfo_struct_sz);
+    }
+  }
+  return res;
+}
+#define INIT_PTRACE_BSD COMMON_INTERCEPT_FUNCTION(ptrace);
+#else
+#define INIT_PTRACE_BSD
+#endif
+
 #include "sanitizer_common_interceptors_netbsd_compat.inc"
 
 namespace __sanitizer {
@@ -10578,6 +10608,7 @@ static void InitializeCommonInterceptors() {
   INIT_HEXDUMP;
   INIT_ARGP_PARSE;
   INIT_CPUSET_GETAFFINITY;
+  INIT_PTRACE_BSD;
 
   INIT___PRINTF_CHK;
 }
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 0ce4e9351bc1da..f47207d1f767f6 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -599,6 +599,7 @@
 #define SANITIZER_INTERCEPT_HEXDUMP SI_FREEBSD
 #define SANITIZER_INTERCEPT_ARGP_PARSE SI_GLIBC
 #define SANITIZER_INTERCEPT_CPUSET_GETAFFINITY SI_FREEBSD
+#define SANITIZER_INTERCEPT_PTRACE_BSD (SI_FREEBSD || SI_NETBSD)
 
 // This macro gives a way for downstream users to override the above
 // interceptor macros irrespective of the platform they are on. They have
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
index 38f968d533b147..8de33ee19092fd 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp
@@ -104,6 +104,8 @@ void *__sanitizer_get_link_map_by_dlopen_handle(void *handle) {
   return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) == 0 ? p : nullptr;
 }
 
+unsigned struct_ptrace_ptrace_io_desc_struct_sz = sizeof(struct ptrace_io_desc);
+unsigned struct_ptrace_ptrace_lwpinfo_struct_sz = sizeof(struct ptrace_lwpinfo);
 unsigned struct_cpuset_sz = sizeof(cpuset_t);
 unsigned struct_cap_rights_sz = sizeof(cap_rights_t);
 unsigned struct_utsname_sz = sizeof(struct utsname);
@@ -155,6 +157,9 @@ const uptr sig_dfl = (uptr)SIG_DFL;
 const uptr sig_err = (uptr)SIG_ERR;
 const uptr sa_siginfo = (uptr)SA_SIGINFO;
 
+int ptrace_pt_io = PT_IO;
+int ptrace_pt_lwpstatus = PT_LWPINFO;
+
 int shmctl_ipc_stat = (int)IPC_STAT;
 int shmctl_ipc_info = (int)IPC_INFO;
 int shmctl_shm_info = (int)SHM_INFO;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
index 43b8a38f39be18..dd722ae045a1bf 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h
@@ -728,6 +728,11 @@ typedef struct __sanitizer_cpuset __sanitizer_cpuset_t;
 extern unsigned struct_cpuset_sz;
 
 typedef unsigned long long __sanitizer_eventfd_t;
+
+extern unsigned struct_ptrace_ptrace_io_desc_struct_sz;
+extern unsigned struct_ptrace_ptrace_lwpinfo_struct_sz;
+extern int ptrace_pt_io;
+extern int ptrace_pt_lwpstatus;
 }  // namespace __sanitizer
 
 #  define CHECK_TYPE_SIZE(TYPE) \
diff --git a/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/ptrace.cpp b/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/ptrace.cpp
new file mode 100644
index 00000000000000..2638c3963161cd
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/FreeBSD/ptrace.cpp
@@ -0,0 +1,27 @@
+// RUN: %clangxx -O0 %s -o %t && %run %t
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main() {
+	pid_t pid;
+	ptrace_lwpinfo pl;
+
+	if ((pid = fork()) == 0) {
+    		execl("/bin/true", "true", NULL);
+		exit(-1);
+	}
+	assert(pid != -1);
+	waitpid(pid, NULL, 0);
+	auto r = ptrace(PT_ATTACH, pid, NULL, 0);
+	assert(!r);
+	waitpid(pid, NULL, 0);
+	r = ptrace(PT_LWPINFO, pid, reinterpret_cast<caddr_t>(&pl), sizeof(pl));
+	assert(!r);
+	r = ptrace(PT_DETACH, pid, NULL, 0);
+	return 0;
+}



More information about the llvm-commits mailing list