From da4e319d16243421639dbf0a63efc6d097db26b8 Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Fri, 5 Sep 2025 11:38:28 +0100 Subject: [PATCH] [Linux][Backtracing] Don't try to use `process_vm_readv()`. We used to try to use `process_vm_readv()` if `CAP_SYS_PTRACE` is enabled. This avoided using signal handlers to catch crashes when we try to read through an invalid pointer, but it complicates the code and it turns out not to work on some Linux kernels where the `process_vm_readv()` syscall is unavailable. rdar://159930644 --- stdlib/public/runtime/CrashHandlerLinux.cpp | 47 ++++++++------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/stdlib/public/runtime/CrashHandlerLinux.cpp b/stdlib/public/runtime/CrashHandlerLinux.cpp index f8e0241be2c1e..970b2cb3af3c5 100644 --- a/stdlib/public/runtime/CrashHandlerLinux.cpp +++ b/stdlib/public/runtime/CrashHandlerLinux.cpp @@ -655,7 +655,6 @@ wait_paused(uint32_t expected, const struct timespec *timeout) char memserver_stack[4096] __attribute__((aligned(SWIFT_PAGE_SIZE))); char memserver_buffer[4096]; int memserver_fd; -bool memserver_has_ptrace; sigjmp_buf memserver_fault_buf; pid_t memserver_pid; @@ -712,21 +711,18 @@ memserver_fault(int sig) { ssize_t __attribute__((noinline)) memserver_read(void *to, const void *from, size_t len) { - if (memserver_has_ptrace) { -// This won't run for older Android APIs anyway, but it can't be compiled -// either, as process_vm_readv() isn't available. -#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 23) - struct iovec local = { to, len }; - struct iovec remote = { const_cast(from), len }; - return process_vm_readv(memserver_pid, &local, 1, &remote, 1, 0); -#endif + /* Earlier versions of this code tried to use process_vm_readv() if they + detected that CAP_SYS_PTRACE was enabled. This is theoretically + slightly safer than using signals and memcpy(), but in practice it + turns out that some kernels don't support process_vm_readv() even + when CAP_SYS_PTRACE is enabled. + + It seems simpler just to use the signal handlers instead. */ + if (!sigsetjmp(memserver_fault_buf, 1)) { + memcpy(to, from, len); + return len; } else { - if (!sigsetjmp(memserver_fault_buf, 1)) { - memcpy(to, from, len); - return len; - } else { - return -1; - } + return -1; } } @@ -739,21 +735,12 @@ memserver_entry(void *dummy __attribute__((unused))) { prctl(PR_SET_NAME, "[backtrace]"); #endif -// process_vm_readv() is not available for older Android APIs. -#if defined(__ANDROID_API__) && __ANDROID_API__ < 23 - memserver_has_ptrace = false; -#else - memserver_has_ptrace = !!prctl(PR_CAPBSET_READ, CAP_SYS_PTRACE); -#endif - - if (!memserver_has_ptrace) { - struct sigaction sa; - sigfillset(&sa.sa_mask); - sa.sa_handler = memserver_fault; - sa.sa_flags = SA_NODEFER; - sigaction(SIGSEGV, &sa, NULL); - sigaction(SIGBUS, &sa, NULL); - } + struct sigaction sa; + sigfillset(&sa.sa_mask); + sa.sa_handler = memserver_fault; + sa.sa_flags = SA_NODEFER; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); for (;;) { struct memserver_req req;