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 #include <memory> 40 #include <mutex> 41 42 #include <android-base/file.h> 43 #include <android-base/unique_fd.h> 44 #include <async_safe/log.h> 45 #include <backtrace/BacktraceMap.h> 46 #include <unwindstack/Memory.h> 47 #include <unwindstack/Regs.h> 48 49 #include "debuggerd/handler.h" 50 #include "tombstoned/tombstoned.h" 51 #include "util.h" 52 53 #include "libdebuggerd/backtrace.h" 54 #include "libdebuggerd/tombstone.h" 55 56 using android::base::unique_fd; 57 using unwindstack::Regs; 58 59 extern "C" bool __linker_enable_fallback_allocator(); 60 extern "C" void __linker_disable_fallback_allocator(); 61 62 // This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace 63 // uses the C++ standard library throughout, but this code runs in the linker, so we'll be using 64 // the linker's malloc instead of the libc one. Switch it out for a replacement, just in case. 65 // 66 // This isn't the default method of dumping because it can fail in cases such as address space 67 // exhaustion. 68 static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) { 69 if (!__linker_enable_fallback_allocator()) { 70 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use"); 71 return; 72 } 73 74 { 75 std::unique_ptr<Regs> regs; 76 77 ThreadInfo thread; 78 thread.pid = getpid(); 79 thread.tid = gettid(); 80 thread.thread_name = get_thread_name(gettid()); 81 thread.registers.reset(Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext)); 82 83 // TODO: Create this once and store it in a global? 84 std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid())); 85 dump_backtrace_thread(output_fd, map.get(), thread); 86 } 87 __linker_disable_fallback_allocator(); 88 } 89 90 static void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo, 91 void* abort_message) { 92 if (!__linker_enable_fallback_allocator()) { 93 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use"); 94 return; 95 } 96 97 engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo, 98 ucontext); 99 __linker_disable_fallback_allocator(); 100 } 101 102 static void iterate_siblings(bool (*callback)(pid_t, int), int output_fd) { 103 pid_t current_tid = gettid(); 104 char buf[BUFSIZ]; 105 snprintf(buf, sizeof(buf), "/proc/%d/task", current_tid); 106 DIR* dir = opendir(buf); 107 108 if (!dir) { 109 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to open %s: %s", buf, strerror(errno)); 110 return; 111 } 112 113 struct dirent* ent; 114 while ((ent = readdir(dir))) { 115 char* end; 116 long tid = strtol(ent->d_name, &end, 10); 117 if (end == ent->d_name || *end != '\0') { 118 continue; 119 } 120 121 if (tid != current_tid) { 122 callback(tid, output_fd); 123 } 124 } 125 closedir(dir); 126 } 127 128 static bool forward_output(int src_fd, int dst_fd, pid_t expected_tid) { 129 // Make sure the thread actually got the signal. 130 struct pollfd pfd = { 131 .fd = src_fd, .events = POLLIN, 132 }; 133 134 // Wait for up to a second for output to start flowing. 135 if (poll(&pfd, 1, 1000) != 1) { 136 return false; 137 } 138 139 pid_t tid; 140 if (TEMP_FAILURE_RETRY(read(src_fd, &tid, sizeof(tid))) != sizeof(tid)) { 141 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to read tid"); 142 return false; 143 } 144 145 if (tid != expected_tid) { 146 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "received tid %d, expected %d", tid, 147 expected_tid); 148 return false; 149 } 150 151 while (true) { 152 char buf[512]; 153 ssize_t rc = TEMP_FAILURE_RETRY(read(src_fd, buf, sizeof(buf))); 154 if (rc == 0) { 155 return true; 156 } else if (rc < 0) { 157 return false; 158 } 159 160 if (!android::base::WriteFully(dst_fd, buf, rc)) { 161 // We failed to write to tombstoned, but there's not much we can do. 162 // Keep reading from src_fd to keep things going. 163 continue; 164 } 165 } 166 } 167 168 struct __attribute__((__packed__)) packed_thread_output { 169 int32_t tid; 170 int32_t fd; 171 }; 172 173 static uint64_t pack_thread_fd(pid_t tid, int fd) { 174 packed_thread_output packed = {.tid = tid, .fd = fd}; 175 uint64_t result; 176 static_assert(sizeof(packed) == sizeof(result)); 177 memcpy(&result, &packed, sizeof(packed)); 178 return result; 179 } 180 181 static std::pair<pid_t, int> unpack_thread_fd(uint64_t value) { 182 packed_thread_output result; 183 memcpy(&result, &value, sizeof(value)); 184 return std::make_pair(result.tid, result.fd); 185 } 186 187 static void trace_handler(siginfo_t* info, ucontext_t* ucontext) { 188 static std::atomic<uint64_t> trace_output(pack_thread_fd(-1, -1)); 189 190 if (info->si_value.sival_int == ~0) { 191 // Asked to dump by the original signal recipient. 192 uint64_t val = trace_output.load(); 193 auto [tid, fd] = unpack_thread_fd(val); 194 if (tid != gettid()) { 195 // We received some other thread's info request? 196 async_safe_format_log(ANDROID_LOG_ERROR, "libc", 197 "thread %d received output fd for thread %d?", gettid(), tid); 198 return; 199 } 200 201 if (!trace_output.compare_exchange_strong(val, pack_thread_fd(-1, -1))) { 202 // Presumably, the timeout in forward_output expired, and the main thread moved on. 203 // If this happened, the main thread closed our fd for us, so just return. 204 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "cmpxchg for thread %d failed", gettid()); 205 return; 206 } 207 208 // Write our tid to the output fd to let the main thread know that we're working. 209 if (TEMP_FAILURE_RETRY(write(fd, &tid, sizeof(tid))) == sizeof(tid)) { 210 debuggerd_fallback_trace(fd, ucontext); 211 } else { 212 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to write to output fd"); 213 } 214 215 close(fd); 216 return; 217 } 218 219 // Only allow one thread to perform a trace at a time. 220 static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER; 221 int ret = pthread_mutex_trylock(&trace_mutex); 222 if (ret != 0) { 223 async_safe_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_try_lock failed: %s", 224 strerror(ret)); 225 return; 226 } 227 228 // Fetch output fd from tombstoned. 229 unique_fd tombstone_socket, output_fd; 230 if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdNativeBacktrace)) { 231 goto exit; 232 } 233 234 dump_backtrace_header(output_fd.get()); 235 236 // Dump our own stack. 237 debuggerd_fallback_trace(output_fd.get(), ucontext); 238 239 // Send a signal to all of our siblings, asking them to dump their stack. 240 iterate_siblings( 241 [](pid_t tid, int output_fd) { 242 // Use a pipe, to be able to detect situations where the thread gracefully exits before 243 // receiving our signal. 244 unique_fd pipe_read, pipe_write; 245 if (!Pipe(&pipe_read, &pipe_write)) { 246 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to create pipe: %s", 247 strerror(errno)); 248 return false; 249 } 250 251 uint64_t expected = pack_thread_fd(-1, -1); 252 if (!trace_output.compare_exchange_strong(expected, 253 pack_thread_fd(tid, pipe_write.release()))) { 254 auto [tid, fd] = unpack_thread_fd(expected); 255 async_safe_format_log(ANDROID_LOG_ERROR, "libc", 256 "thread %d is already outputting to fd %d?", tid, fd); 257 return false; 258 } 259 260 siginfo_t siginfo = {}; 261 siginfo.si_code = SI_QUEUE; 262 siginfo.si_value.sival_int = ~0; 263 siginfo.si_pid = getpid(); 264 siginfo.si_uid = getuid(); 265 266 if (syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, DEBUGGER_SIGNAL, &siginfo) != 0) { 267 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to send trace signal to %d: %s", 268 tid, strerror(errno)); 269 return false; 270 } 271 272 bool success = forward_output(pipe_read.get(), output_fd, tid); 273 if (!success) { 274 async_safe_format_log(ANDROID_LOG_ERROR, "libc", 275 "timeout expired while waiting for thread %d to dump", tid); 276 } 277 278 // Regardless of whether the poll succeeds, check to see if the thread took fd ownership. 279 uint64_t post_wait = trace_output.exchange(pack_thread_fd(-1, -1)); 280 if (post_wait != pack_thread_fd(-1, -1)) { 281 auto [tid, fd] = unpack_thread_fd(post_wait); 282 if (fd != -1) { 283 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "closing fd %d for thread %d", fd, tid); 284 close(fd); 285 } 286 } 287 288 return true; 289 }, 290 output_fd.get()); 291 292 dump_backtrace_footer(output_fd.get()); 293 tombstoned_notify_completion(tombstone_socket.get()); 294 295 exit: 296 pthread_mutex_unlock(&trace_mutex); 297 } 298 299 static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) { 300 // Only allow one thread to handle a crash at a time (this can happen multiple times without 301 // exit, since tombstones can be requested without a real crash happening.) 302 static std::recursive_mutex crash_mutex; 303 static int lock_count; 304 305 crash_mutex.lock(); 306 if (lock_count++ > 0) { 307 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "recursed signal handler call, exiting"); 308 _exit(1); 309 } 310 311 unique_fd tombstone_socket, output_fd; 312 bool tombstoned_connected = 313 tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdTombstone); 314 debuggerd_fallback_tombstone(output_fd.get(), ucontext, info, abort_message); 315 if (tombstoned_connected) { 316 tombstoned_notify_completion(tombstone_socket.get()); 317 } 318 319 --lock_count; 320 crash_mutex.unlock(); 321 } 322 323 extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext, 324 void* abort_message) { 325 if (info->si_signo == DEBUGGER_SIGNAL && info->si_value.sival_int != 0) { 326 return trace_handler(info, ucontext); 327 } else { 328 return crash_handler(info, ucontext, abort_message); 329 } 330 } 331