1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <dirent.h> 30 #include <fcntl.h> 31 #include <poll.h> 32 #include <pthread.h> 33 #include <stddef.h> 34 #include <sys/ucontext.h> 35 #include <syscall.h> 36 #include <unistd.h> 37 38 #include <atomic> 39 40 #include <android-base/file.h> 41 #include <android-base/unique_fd.h> 42 #include <async_safe/log.h> 43 44 #include "debuggerd/handler.h" 45 #include "tombstoned/tombstoned.h" 46 #include "util.h" 47 48 #include "backtrace.h" 49 #include "tombstone.h" 50 51 using android::base::unique_fd; 52 53 extern "C" void __linker_enable_fallback_allocator(); 54 extern "C" void __linker_disable_fallback_allocator(); 55 56 // This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace 57 // uses the C++ standard library throughout, but this code runs in the linker, so we'll be using 58 // the linker's malloc instead of the libc one. Switch it out for a replacement, just in case. 59 // 60 // This isn't the default method of dumping because it can fail in cases such as address space 61 // exhaustion. 62 static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) { 63 __linker_enable_fallback_allocator(); 64 dump_backtrace_ucontext(output_fd, ucontext); 65 __linker_disable_fallback_allocator(); 66 } 67 68 static void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo, 69 void* abort_message) { 70 __linker_enable_fallback_allocator(); 71 engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo, 72 ucontext); 73 __linker_disable_fallback_allocator(); 74 } 75 76 static void iterate_siblings(bool (*callback)(pid_t, int), int output_fd) { 77 pid_t current_tid = gettid(); 78 char buf[BUFSIZ]; 79 snprintf(buf, sizeof(buf), "/proc/%d/task", current_tid); 80 DIR* dir = opendir(buf); 81 82 if (!dir) { 83 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to open %s: %s", buf, strerror(errno)); 84 return; 85 } 86 87 struct dirent* ent; 88 while ((ent = readdir(dir))) { 89 char* end; 90 long tid = strtol(ent->d_name, &end, 10); 91 if (end == ent->d_name || *end != '\0') { 92 continue; 93 } 94 95 if (tid != current_tid) { 96 callback(tid, output_fd); 97 } 98 } 99 closedir(dir); 100 } 101 102 static bool forward_output(int src_fd, int dst_fd) { 103 // Make sure the thread actually got the signal. 104 struct pollfd pfd = { 105 .fd = src_fd, .events = POLLIN, 106 }; 107 108 // Wait for up to a second for output to start flowing. 109 if (poll(&pfd, 1, 1000) != 1) { 110 return false; 111 } 112 113 while (true) { 114 char buf[512]; 115 ssize_t rc = TEMP_FAILURE_RETRY(read(src_fd, buf, sizeof(buf))); 116 if (rc == 0) { 117 return true; 118 } else if (rc < 0) { 119 return false; 120 } 121 122 if (!android::base::WriteFully(dst_fd, buf, rc)) { 123 // We failed to write to tombstoned, but there's not much we can do. 124 // Keep reading from src_fd to keep things going. 125 continue; 126 } 127 } 128 } 129 130 static void trace_handler(siginfo_t* info, ucontext_t* ucontext) { 131 static std::atomic<int> trace_output_fd(-1); 132 133 if (info->si_value.sival_int == ~0) { 134 // Asked to dump by the original signal recipient. 135 debuggerd_fallback_trace(trace_output_fd, ucontext); 136 137 int tmp = trace_output_fd.load(); 138 trace_output_fd.store(-1); 139 close(tmp); 140 return; 141 } 142 143 // Only allow one thread to perform a trace at a time. 144 static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER; 145 int ret = pthread_mutex_trylock(&trace_mutex); 146 if (ret != 0) { 147 async_safe_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_try_lock failed: %s", 148 strerror(ret)); 149 return; 150 } 151 152 // Fetch output fd from tombstoned. 153 unique_fd tombstone_socket, output_fd; 154 if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdNativeBacktrace)) { 155 goto exit; 156 } 157 158 dump_backtrace_header(output_fd.get()); 159 160 // Dump our own stack. 161 debuggerd_fallback_trace(output_fd.get(), ucontext); 162 163 // Send a signal to all of our siblings, asking them to dump their stack. 164 iterate_siblings( 165 [](pid_t tid, int output_fd) { 166 // Use a pipe, to be able to detect situations where the thread gracefully exits before 167 // receiving our signal. 168 unique_fd pipe_read, pipe_write; 169 if (!Pipe(&pipe_read, &pipe_write)) { 170 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to create pipe: %s", 171 strerror(errno)); 172 return false; 173 } 174 175 trace_output_fd.store(pipe_write.get()); 176 177 siginfo_t siginfo = {}; 178 siginfo.si_code = SI_QUEUE; 179 siginfo.si_value.sival_int = ~0; 180 siginfo.si_pid = getpid(); 181 siginfo.si_uid = getuid(); 182 183 if (syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, DEBUGGER_SIGNAL, &siginfo) != 0) { 184 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to send trace signal to %d: %s", 185 tid, strerror(errno)); 186 return false; 187 } 188 189 bool success = forward_output(pipe_read.get(), output_fd); 190 if (success) { 191 // The signaled thread has closed trace_output_fd already. 192 (void)pipe_write.release(); 193 } else { 194 trace_output_fd.store(-1); 195 } 196 197 return true; 198 }, 199 output_fd.get()); 200 201 dump_backtrace_footer(output_fd.get()); 202 tombstoned_notify_completion(tombstone_socket.get()); 203 204 exit: 205 pthread_mutex_unlock(&trace_mutex); 206 } 207 208 static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) { 209 // Only allow one thread to handle a crash. 210 static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER; 211 int ret = pthread_mutex_lock(&crash_mutex); 212 if (ret != 0) { 213 async_safe_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret)); 214 return; 215 } 216 217 unique_fd tombstone_socket, output_fd; 218 bool tombstoned_connected = 219 tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdTombstone); 220 debuggerd_fallback_tombstone(output_fd.get(), ucontext, info, abort_message); 221 if (tombstoned_connected) { 222 tombstoned_notify_completion(tombstone_socket.get()); 223 } 224 } 225 226 extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext, 227 void* abort_message) { 228 if (info->si_signo == DEBUGGER_SIGNAL) { 229 return trace_handler(info, ucontext); 230 } else { 231 return crash_handler(info, ucontext, abort_message); 232 } 233 } 234