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