Home | History | Annotate | Download | only in handler
      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