LCOV - code coverage report
Current view: top level - toolkit/crashreporter/breakpad-client/linux/handler - exception_handler.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 261 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2010 Google Inc.
       2             : // All rights reserved.
       3             : //
       4             : // Redistribution and use in source and binary forms, with or without
       5             : // modification, are permitted provided that the following conditions are
       6             : // met:
       7             : //
       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
      11             : // copyright notice, this list of conditions and the following disclaimer
      12             : // in the documentation and/or other materials provided with the
      13             : // distribution.
      14             : //     * Neither the name of Google Inc. nor the names of its
      15             : // contributors may be used to endorse or promote products derived from
      16             : // this software without specific prior written permission.
      17             : //
      18             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      19             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      20             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      21             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      22             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      23             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      24             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      25             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      26             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      28             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29             : 
      30             : // The ExceptionHandler object installs signal handlers for a number of
      31             : // signals. We rely on the signal handler running on the thread which crashed
      32             : // in order to identify it. This is true of the synchronous signals (SEGV etc),
      33             : // but not true of ABRT. Thus, if you send ABRT to yourself in a program which
      34             : // uses ExceptionHandler, you need to use tgkill to direct it to the current
      35             : // thread.
      36             : //
      37             : // The signal flow looks like this:
      38             : //
      39             : //   SignalHandler (uses a global stack of ExceptionHandler objects to find
      40             : //        |         one to handle the signal. If the first rejects it, try
      41             : //        |         the second etc...)
      42             : //        V
      43             : //   HandleSignal ----------------------------| (clones a new process which
      44             : //        |                                   |  shares an address space with
      45             : //   (wait for cloned                         |  the crashed process. This
      46             : //     process)                               |  allows us to ptrace the crashed
      47             : //        |                                   |  process)
      48             : //        V                                   V
      49             : //   (set signal handler to             ThreadEntry (static function to bounce
      50             : //    SIG_DFL and rethrow,                    |      back into the object)
      51             : //    killing the crashed                     |
      52             : //    process)                                V
      53             : //                                          DoDump  (writes minidump)
      54             : //                                            |
      55             : //                                            V
      56             : //                                         sys_exit
      57             : //
      58             : 
      59             : // This code is a little fragmented. Different functions of the ExceptionHandler
      60             : // class run in a number of different contexts. Some of them run in a normal
      61             : // context and are easy to code, others run in a compromised context and the
      62             : // restrictions at the top of minidump_writer.cc apply: no libc and use the
      63             : // alternative malloc. Each function should have comment above it detailing the
      64             : // context which it runs in.
      65             : 
      66             : #include "linux/handler/exception_handler.h"
      67             : 
      68             : #include <errno.h>
      69             : #include <fcntl.h>
      70             : #include <linux/limits.h>
      71             : #include <pthread.h>
      72             : #include <sched.h>
      73             : #include <signal.h>
      74             : #include <stdio.h>
      75             : #include <sys/mman.h>
      76             : #include <sys/prctl.h>
      77             : #include <sys/syscall.h>
      78             : #include <sys/wait.h>
      79             : #include <unistd.h>
      80             : 
      81             : #include <sys/signal.h>
      82             : #include <sys/ucontext.h>
      83             : #include <sys/user.h>
      84             : #include <ucontext.h>
      85             : 
      86             : #include <algorithm>
      87             : #include <utility>
      88             : #include <vector>
      89             : 
      90             : #include "common/basictypes.h"
      91             : #include "common/linux/linux_libc_support.h"
      92             : #include "common/memory.h"
      93             : #include "linux/log/log.h"
      94             : #include "linux/microdump_writer/microdump_writer.h"
      95             : #include "linux/minidump_writer/linux_dumper.h"
      96             : #include "linux/minidump_writer/minidump_writer.h"
      97             : #include "common/linux/eintr_wrapper.h"
      98             : #include "third_party/lss/linux_syscall_support.h"
      99             : 
     100             : #if defined(__ANDROID__)
     101             : #include "linux/sched.h"
     102             : #endif
     103             : 
     104             : #ifndef PR_SET_PTRACER
     105             : #define PR_SET_PTRACER 0x59616d61
     106             : #endif
     107             : 
     108             : // A wrapper for the tgkill syscall: send a signal to a specific thread.
     109           0 : static int tgkill(pid_t tgid, pid_t tid, int sig) {
     110           0 :   return syscall(__NR_tgkill, tgid, tid, sig);
     111             :   return 0;
     112             : }
     113             : 
     114             : namespace google_breakpad {
     115             : 
     116             : namespace {
     117             : // The list of signals which we consider to be crashes. The default action for
     118             : // all these signals must be Core (see man 7 signal) because we rethrow the
     119             : // signal after handling it and expect that it'll be fatal.
     120             : const int kExceptionSignals[] = {
     121             :   SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, SIGTRAP
     122             : };
     123             : const int kNumHandledSignals =
     124             :     sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]);
     125             : struct sigaction old_handlers[kNumHandledSignals];
     126             : bool handlers_installed = false;
     127             : 
     128             : // InstallAlternateStackLocked will store the newly installed stack in new_stack
     129             : // and (if it exists) the previously installed stack in old_stack.
     130             : stack_t old_stack;
     131             : stack_t new_stack;
     132             : bool stack_installed = false;
     133             : 
     134             : // Create an alternative stack to run the signal handlers on. This is done since
     135             : // the signal might have been caused by a stack overflow.
     136             : // Runs before crashing: normal context.
     137           0 : void InstallAlternateStackLocked() {
     138           0 :   if (stack_installed)
     139           0 :     return;
     140             : 
     141           0 :   memset(&old_stack, 0, sizeof(old_stack));
     142           0 :   memset(&new_stack, 0, sizeof(new_stack));
     143             : 
     144             :   // SIGSTKSZ may be too small to prevent the signal handlers from overrunning
     145             :   // the alternative stack. Ensure that the size of the alternative stack is
     146             :   // large enough.
     147           0 :   static const unsigned kSigStackSize = std::max(16384, SIGSTKSZ);
     148             : 
     149             :   // Only set an alternative stack if there isn't already one, or if the current
     150             :   // one is too small.
     151           0 :   if (sys_sigaltstack(NULL, &old_stack) == -1 || !old_stack.ss_sp ||
     152           0 :       old_stack.ss_size < kSigStackSize) {
     153           0 :     new_stack.ss_sp = calloc(1, kSigStackSize);
     154           0 :     new_stack.ss_size = kSigStackSize;
     155             : 
     156           0 :     if (sys_sigaltstack(&new_stack, NULL) == -1) {
     157           0 :       free(new_stack.ss_sp);
     158           0 :       return;
     159             :     }
     160           0 :     stack_installed = true;
     161             :   }
     162             : }
     163             : 
     164             : // Runs before crashing: normal context.
     165           0 : void RestoreAlternateStackLocked() {
     166           0 :   if (!stack_installed)
     167           0 :     return;
     168             : 
     169             :   stack_t current_stack;
     170           0 :   if (sys_sigaltstack(NULL, &current_stack) == -1)
     171           0 :     return;
     172             : 
     173             :   // Only restore the old_stack if the current alternative stack is the one
     174             :   // installed by the call to InstallAlternateStackLocked.
     175           0 :   if (current_stack.ss_sp == new_stack.ss_sp) {
     176           0 :     if (old_stack.ss_sp) {
     177           0 :       if (sys_sigaltstack(&old_stack, NULL) == -1)
     178           0 :         return;
     179             :     } else {
     180             :       stack_t disable_stack;
     181           0 :       disable_stack.ss_flags = SS_DISABLE;
     182           0 :       if (sys_sigaltstack(&disable_stack, NULL) == -1)
     183           0 :         return;
     184             :     }
     185             :   }
     186             : 
     187           0 :   free(new_stack.ss_sp);
     188           0 :   stack_installed = false;
     189             : }
     190             : 
     191           0 : void InstallDefaultHandler(int sig) {
     192             : #if defined(__ANDROID__)
     193             :   // Android L+ expose signal and sigaction symbols that override the system
     194             :   // ones. There is a bug in these functions where a request to set the handler
     195             :   // to SIG_DFL is ignored. In that case, an infinite loop is entered as the
     196             :   // signal is repeatedly sent to breakpad's signal handler.
     197             :   // To work around this, directly call the system's sigaction.
     198             :   struct kernel_sigaction sa;
     199             :   memset(&sa, 0, sizeof(sa));
     200             :   sys_sigemptyset(&sa.sa_mask);
     201             :   sa.sa_handler_ = SIG_DFL;
     202             :   sa.sa_flags = SA_RESTART;
     203             :   sys_rt_sigaction(sig, &sa, NULL, sizeof(kernel_sigset_t));
     204             : #else
     205           0 :   signal(sig, SIG_DFL);
     206             : #endif
     207           0 : }
     208             : 
     209             : // The global exception handler stack. This is needed because there may exist
     210             : // multiple ExceptionHandler instances in a process. Each will have itself
     211             : // registered in this stack.
     212             : std::vector<ExceptionHandler*>* g_handler_stack_ = NULL;
     213             : pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER;
     214             : 
     215             : // sizeof(CrashContext) can be too big w.r.t the size of alternatate stack
     216             : // for SignalHandler(). Keep the crash context as a .bss field. Exception
     217             : // handlers are serialized by the |g_handler_stack_mutex_| and at most one at a
     218             : // time can use |g_crash_context_|.
     219             : ExceptionHandler::CrashContext g_crash_context_;
     220             : 
     221             : }  // namespace
     222             : 
     223             : // Runs before crashing: normal context.
     224           0 : ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
     225             :                                    FilterCallback filter,
     226             :                                    MinidumpCallback callback,
     227             :                                    void* callback_context,
     228             :                                    bool install_handler,
     229           0 :                                    const int server_fd)
     230             :     : filter_(filter),
     231             :       callback_(callback),
     232             :       callback_context_(callback_context),
     233             :       minidump_descriptor_(descriptor),
     234           0 :       crash_handler_(NULL) {
     235           0 :   if (server_fd >= 0)
     236           0 :     crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd));
     237             : 
     238           0 :   if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() &&
     239           0 :       !minidump_descriptor_.IsMicrodumpOnConsole())
     240           0 :     minidump_descriptor_.UpdatePath();
     241             : 
     242             : #if defined(__ANDROID__)
     243             :   if (minidump_descriptor_.IsMicrodumpOnConsole())
     244             :     logger::initializeCrashLogWriter();
     245             : #endif
     246             : 
     247           0 :   pthread_mutex_lock(&g_handler_stack_mutex_);
     248             : 
     249             :   // Pre-fault the crash context struct. This is to avoid failing due to OOM
     250             :   // if handling an exception when the process ran out of virtual memory.
     251           0 :   memset(&g_crash_context_, 0, sizeof(g_crash_context_));
     252             : 
     253           0 :   if (!g_handler_stack_)
     254           0 :     g_handler_stack_ = new std::vector<ExceptionHandler*>;
     255           0 :   if (install_handler) {
     256           0 :     InstallAlternateStackLocked();
     257           0 :     InstallHandlersLocked();
     258             :   }
     259           0 :   g_handler_stack_->push_back(this);
     260           0 :   pthread_mutex_unlock(&g_handler_stack_mutex_);
     261           0 : }
     262             : 
     263             : // Runs before crashing: normal context.
     264           0 : ExceptionHandler::~ExceptionHandler() {
     265           0 :   pthread_mutex_lock(&g_handler_stack_mutex_);
     266             :   std::vector<ExceptionHandler*>::iterator handler =
     267           0 :       std::find(g_handler_stack_->begin(), g_handler_stack_->end(), this);
     268           0 :   g_handler_stack_->erase(handler);
     269           0 :   if (g_handler_stack_->empty()) {
     270           0 :     delete g_handler_stack_;
     271           0 :     g_handler_stack_ = NULL;
     272           0 :     RestoreAlternateStackLocked();
     273           0 :     RestoreHandlersLocked();
     274             :   }
     275           0 :   pthread_mutex_unlock(&g_handler_stack_mutex_);
     276           0 : }
     277             : 
     278             : // Runs before crashing: normal context.
     279             : // static
     280           0 : bool ExceptionHandler::InstallHandlersLocked() {
     281           0 :   if (handlers_installed)
     282           0 :     return false;
     283             : 
     284             :   // Fail if unable to store all the old handlers.
     285           0 :   for (int i = 0; i < kNumHandledSignals; ++i) {
     286           0 :     if (sigaction(kExceptionSignals[i], NULL, &old_handlers[i]) == -1)
     287           0 :       return false;
     288             :   }
     289             : 
     290             :   struct sigaction sa;
     291           0 :   memset(&sa, 0, sizeof(sa));
     292           0 :   sigemptyset(&sa.sa_mask);
     293             : 
     294             :   // Mask all exception signals when we're handling one of them.
     295           0 :   for (int i = 0; i < kNumHandledSignals; ++i)
     296           0 :     sigaddset(&sa.sa_mask, kExceptionSignals[i]);
     297             : 
     298           0 :   sa.sa_sigaction = SignalHandler;
     299           0 :   sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
     300             : 
     301           0 :   for (int i = 0; i < kNumHandledSignals; ++i) {
     302           0 :     if (sigaction(kExceptionSignals[i], &sa, NULL) == -1) {
     303             :       // At this point it is impractical to back out changes, and so failure to
     304             :       // install a signal is intentionally ignored.
     305             :     }
     306             :   }
     307           0 :   handlers_installed = true;
     308           0 :   return true;
     309             : }
     310             : 
     311             : // This function runs in a compromised context: see the top of the file.
     312             : // Runs on the crashing thread.
     313             : // static
     314           0 : void ExceptionHandler::RestoreHandlersLocked() {
     315           0 :   if (!handlers_installed)
     316           0 :     return;
     317             : 
     318           0 :   for (int i = 0; i < kNumHandledSignals; ++i) {
     319           0 :     if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
     320           0 :       InstallDefaultHandler(kExceptionSignals[i]);
     321             :     }
     322             :   }
     323           0 :   handlers_installed = false;
     324             : }
     325             : 
     326             : // void ExceptionHandler::set_crash_handler(HandlerCallback callback) {
     327             : //   crash_handler_ = callback;
     328             : // }
     329             : 
     330             : // This function runs in a compromised context: see the top of the file.
     331             : // Runs on the crashing thread.
     332             : // static
     333           0 : void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
     334             :   // All the exception signals are blocked at this point.
     335           0 :   pthread_mutex_lock(&g_handler_stack_mutex_);
     336             : 
     337             :   // Sometimes, Breakpad runs inside a process where some other buggy code
     338             :   // saves and restores signal handlers temporarily with 'signal'
     339             :   // instead of 'sigaction'. This loses the SA_SIGINFO flag associated
     340             :   // with this function. As a consequence, the values of 'info' and 'uc'
     341             :   // become totally bogus, generally inducing a crash.
     342             :   //
     343             :   // The following code tries to detect this case. When it does, it
     344             :   // resets the signal handlers with sigaction + SA_SIGINFO and returns.
     345             :   // This forces the signal to be thrown again, but this time the kernel
     346             :   // will call the function with the right arguments.
     347             :   struct sigaction cur_handler;
     348           0 :   if (sigaction(sig, NULL, &cur_handler) == 0 &&
     349           0 :       (cur_handler.sa_flags & SA_SIGINFO) == 0) {
     350             :     // Reset signal handler with the right flags.
     351           0 :     sigemptyset(&cur_handler.sa_mask);
     352           0 :     sigaddset(&cur_handler.sa_mask, sig);
     353             : 
     354           0 :     cur_handler.sa_sigaction = SignalHandler;
     355           0 :     cur_handler.sa_flags = SA_ONSTACK | SA_SIGINFO;
     356             : 
     357           0 :     if (sigaction(sig, &cur_handler, NULL) == -1) {
     358             :       // When resetting the handler fails, try to reset the
     359             :       // default one to avoid an infinite loop here.
     360           0 :       InstallDefaultHandler(sig);
     361             :     }
     362           0 :     pthread_mutex_unlock(&g_handler_stack_mutex_);
     363           0 :     return;
     364             :   }
     365             : 
     366           0 :   bool handled = false;
     367           0 :   for (int i = g_handler_stack_->size() - 1; !handled && i >= 0; --i) {
     368           0 :     handled = (*g_handler_stack_)[i]->HandleSignal(sig, info, uc);
     369             :   }
     370             : 
     371             :   // Upon returning from this signal handler, sig will become unmasked and then
     372             :   // it will be retriggered. If one of the ExceptionHandlers handled it
     373             :   // successfully, restore the default handler. Otherwise, restore the
     374             :   // previously installed handler. Then, when the signal is retriggered, it will
     375             :   // be delivered to the appropriate handler.
     376           0 :   if (handled) {
     377           0 :     InstallDefaultHandler(sig);
     378             :   } else {
     379           0 :     RestoreHandlersLocked();
     380             :   }
     381             : 
     382           0 :   pthread_mutex_unlock(&g_handler_stack_mutex_);
     383             : 
     384             :   // info->si_code <= 0 iff SI_FROMUSER (SI_FROMKERNEL otherwise).
     385           0 :   if (info->si_code <= 0 || sig == SIGABRT) {
     386             :     // This signal was triggered by somebody sending us the signal with kill().
     387             :     // In order to retrigger it, we have to queue a new signal by calling
     388             :     // kill() ourselves.  The special case (si_pid == 0 && sig == SIGABRT) is
     389             :     // due to the kernel sending a SIGABRT from a user request via SysRQ.
     390           0 :     if (tgkill(getpid(), syscall(__NR_gettid), sig) < 0) {
     391             :       // If we failed to kill ourselves (e.g. because a sandbox disallows us
     392             :       // to do so), we instead resort to terminating our process. This will
     393             :       // result in an incorrect exit code.
     394           0 :       _exit(1);
     395             :     }
     396             :   } else {
     397             :     // This was a synchronous signal triggered by a hard fault (e.g. SIGSEGV).
     398             :     // No need to reissue the signal. It will automatically trigger again,
     399             :     // when we return from the signal handler.
     400             :   }
     401             : }
     402             : 
     403             : struct ThreadArgument {
     404             :   pid_t pid;  // the crashing process
     405             :   const MinidumpDescriptor* minidump_descriptor;
     406             :   ExceptionHandler* handler;
     407             :   const void* context;  // a CrashContext structure
     408             :   size_t context_size;
     409             : };
     410             : 
     411             : // This is the entry function for the cloned process. We are in a compromised
     412             : // context here: see the top of the file.
     413             : // static
     414           0 : int ExceptionHandler::ThreadEntry(void *arg) {
     415           0 :   const ThreadArgument *thread_arg = reinterpret_cast<ThreadArgument*>(arg);
     416             : 
     417             :   // Block here until the crashing process unblocks us when
     418             :   // we're allowed to use ptrace
     419           0 :   thread_arg->handler->WaitForContinueSignal();
     420             : 
     421           0 :   return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context,
     422           0 :                                      thread_arg->context_size) == false;
     423             : }
     424             : 
     425             : // This function runs in a compromised context: see the top of the file.
     426             : // Runs on the crashing thread.
     427           0 : bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
     428           0 :   if (filter_ && !filter_(callback_context_))
     429           0 :     return false;
     430             : 
     431             :   // Allow ourselves to be dumped if the signal is trusted.
     432           0 :   bool signal_trusted = info->si_code > 0;
     433           0 :   bool signal_pid_trusted = info->si_code == SI_USER ||
     434           0 :       info->si_code == SI_TKILL;
     435           0 :   if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) {
     436           0 :     sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
     437             :   }
     438             : 
     439             :   // Fill in all the holes in the struct to make Valgrind happy.
     440           0 :   memset(&g_crash_context_, 0, sizeof(g_crash_context_));
     441           0 :   memcpy(&g_crash_context_.siginfo, info, sizeof(siginfo_t));
     442           0 :   memcpy(&g_crash_context_.context, uc, sizeof(struct ucontext));
     443             : #if defined(__aarch64__)
     444             :   struct ucontext* uc_ptr = (struct ucontext*)uc;
     445             :   struct fpsimd_context* fp_ptr =
     446             :       (struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved;
     447             :   if (fp_ptr->head.magic == FPSIMD_MAGIC) {
     448             :     memcpy(&g_crash_context_.float_state, fp_ptr,
     449             :            sizeof(g_crash_context_.float_state));
     450             :   }
     451             : #elif !defined(__ARM_EABI__) && !defined(__mips__)
     452             :   // FP state is not part of user ABI on ARM Linux.
     453             :   // In case of MIPS Linux FP state is already part of struct ucontext
     454             :   // and 'float_state' is not a member of CrashContext.
     455           0 :   struct ucontext* uc_ptr = (struct ucontext*)uc;
     456           0 :   if (uc_ptr->uc_mcontext.fpregs) {
     457           0 :     memcpy(&g_crash_context_.float_state, uc_ptr->uc_mcontext.fpregs,
     458           0 :            sizeof(g_crash_context_.float_state));
     459             :   }
     460             : #endif
     461           0 :   g_crash_context_.tid = syscall(__NR_gettid);
     462           0 :   if (crash_handler_ != NULL) {
     463           0 :     if (crash_handler_(&g_crash_context_, sizeof(g_crash_context_),
     464           0 :                        callback_context_)) {
     465           0 :       return true;
     466             :     }
     467             :   }
     468           0 :   return GenerateDump(&g_crash_context_);
     469             : }
     470             : 
     471             : // This is a public interface to HandleSignal that allows the client to
     472             : // generate a crash dump. This function may run in a compromised context.
     473           0 : bool ExceptionHandler::SimulateSignalDelivery(int sig) {
     474           0 :   siginfo_t siginfo = {};
     475             :   // Mimic a trusted signal to allow tracing the process (see
     476             :   // ExceptionHandler::HandleSignal().
     477           0 :   siginfo.si_code = SI_USER;
     478           0 :   siginfo.si_pid = getpid();
     479             :   struct ucontext context;
     480           0 :   getcontext(&context);
     481           0 :   return HandleSignal(sig, &siginfo, &context);
     482             : }
     483             : 
     484             : // This function may run in a compromised context: see the top of the file.
     485           0 : bool ExceptionHandler::GenerateDump(CrashContext *context) {
     486           0 :   if (IsOutOfProcess())
     487           0 :     return crash_generation_client_->RequestDump(context, sizeof(*context));
     488             : 
     489             :   // Allocating too much stack isn't a problem, and better to err on the side
     490             :   // of caution than smash it into random locations.
     491             :   static const unsigned kChildStackSize = 16000;
     492           0 :   PageAllocator allocator;
     493           0 :   uint8_t* stack = reinterpret_cast<uint8_t*>(allocator.Alloc(kChildStackSize));
     494           0 :   if (!stack)
     495           0 :     return false;
     496             :   // clone() needs the top-most address. (scrub just to be safe)
     497           0 :   stack += kChildStackSize;
     498           0 :   my_memset(stack - 16, 0, 16);
     499             : 
     500             :   ThreadArgument thread_arg;
     501           0 :   thread_arg.handler = this;
     502           0 :   thread_arg.minidump_descriptor = &minidump_descriptor_;
     503           0 :   thread_arg.pid = getpid();
     504           0 :   thread_arg.context = context;
     505           0 :   thread_arg.context_size = sizeof(*context);
     506             : 
     507             :   // We need to explicitly enable ptrace of parent processes on some
     508             :   // kernels, but we need to know the PID of the cloned process before we
     509             :   // can do this. Create a pipe here which we can use to block the
     510             :   // cloned process after creating it, until we have explicitly enabled ptrace
     511           0 :   if (sys_pipe(fdes) == -1) {
     512             :     // Creating the pipe failed. We'll log an error but carry on anyway,
     513             :     // as we'll probably still get a useful crash report. All that will happen
     514             :     // is the write() and read() calls will fail with EBADF
     515             :     static const char no_pipe_msg[] = "ExceptionHandler::GenerateDump "
     516             :                                       "sys_pipe failed:";
     517           0 :     logger::write(no_pipe_msg, sizeof(no_pipe_msg) - 1);
     518           0 :     logger::write(strerror(errno), strlen(strerror(errno)));
     519           0 :     logger::write("\n", 1);
     520             : 
     521             :     // Ensure fdes[0] and fdes[1] are invalid file descriptors.
     522           0 :     fdes[0] = fdes[1] = -1;
     523             :   }
     524             : 
     525             :   const pid_t child = sys_clone(
     526             :       ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
     527           0 :       &thread_arg, NULL, NULL, NULL);
     528           0 :   if (child == -1) {
     529           0 :     sys_close(fdes[0]);
     530           0 :     sys_close(fdes[1]);
     531           0 :     return false;
     532             :   }
     533             : 
     534           0 :   if (child != 0) {
     535             :     static const char clonedMsg[] =
     536             :       "ExceptionHandler::GenerateDump cloned child ";
     537             :     char pidMsg[32];
     538             : 
     539           0 :     unsigned int pidLen = my_uint_len(child);
     540           0 :     my_uitos(pidMsg, child, pidLen);
     541             : 
     542           0 :     logger::write(clonedMsg, my_strlen(clonedMsg));
     543           0 :     logger::write(pidMsg, pidLen);
     544           0 :     logger::write("\n", 1);
     545             :   } else {
     546             :     static const char childMsg[] =
     547             :       "ExceptionHandler::GenerateDump I'm the child\n";
     548           0 :     logger::write(childMsg, my_strlen(childMsg));
     549             :   }
     550             : 
     551             :   // Allow the child to ptrace us
     552           0 :   sys_prctl(PR_SET_PTRACER, child, 0, 0, 0);
     553           0 :   SendContinueSignalToChild();
     554             :   int status;
     555           0 :   const int r = HANDLE_EINTR(sys_waitpid(child, &status, __WALL));
     556             : 
     557           0 :   sys_close(fdes[0]);
     558           0 :   sys_close(fdes[1]);
     559             : 
     560           0 :   if (r == -1) {
     561             :     static const char msg[] = "ExceptionHandler::GenerateDump waitpid failed:";
     562           0 :     logger::write(msg, sizeof(msg) - 1);
     563           0 :     logger::write(strerror(errno), strlen(strerror(errno)));
     564           0 :     logger::write("\n", 1);
     565             :   }
     566             : 
     567           0 :   bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0;
     568           0 :   if (callback_)
     569           0 :     success = callback_(minidump_descriptor_, callback_context_, success);
     570           0 :   return success;
     571             : }
     572             : 
     573             : // This function runs in a compromised context: see the top of the file.
     574           0 : void ExceptionHandler::SendContinueSignalToChild() {
     575             :   static const char okToContinueMessage = 'a';
     576             :   int r;
     577           0 :   r = HANDLE_EINTR(sys_write(fdes[1], &okToContinueMessage, sizeof(char)));
     578           0 :   if (r == -1) {
     579             :     static const char msg[] = "ExceptionHandler::SendContinueSignalToChild "
     580             :                               "sys_write failed:";
     581           0 :     logger::write(msg, sizeof(msg) - 1);
     582           0 :     logger::write(strerror(errno), strlen(strerror(errno)));
     583           0 :     logger::write("\n", 1);
     584             :   }
     585             : 
     586           0 :   const char* msg = "ExceptionHandler::SendContinueSignalToChild sent continue signal to child\n";
     587           0 :   logger::write(msg, my_strlen(msg));
     588           0 : }
     589             : 
     590             : // This function runs in a compromised context: see the top of the file.
     591             : // Runs on the cloned process.
     592           0 : void ExceptionHandler::WaitForContinueSignal() {
     593             :   int r;
     594             :   char receivedMessage;
     595             : 
     596           0 :   const char* waitMsg = "ExceptionHandler::WaitForContinueSignal waiting for continue signal...\n";
     597           0 :   logger::write(waitMsg, my_strlen(waitMsg));
     598             : 
     599           0 :   r = HANDLE_EINTR(sys_read(fdes[0], &receivedMessage, sizeof(char)));
     600           0 :   if (r == -1) {
     601             :     static const char msg[] = "ExceptionHandler::WaitForContinueSignal "
     602             :                               "sys_read failed:";
     603           0 :     logger::write(msg, sizeof(msg) - 1);
     604           0 :     logger::write(strerror(errno), strlen(strerror(errno)));
     605           0 :     logger::write("\n", 1);
     606             :   }
     607           0 : }
     608             : 
     609             : // This function runs in a compromised context: see the top of the file.
     610             : // Runs on the cloned process.
     611           0 : bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
     612             :                               size_t context_size) {
     613           0 :   if (minidump_descriptor_.IsMicrodumpOnConsole()) {
     614           0 :     return google_breakpad::WriteMicrodump(
     615             :         crashing_process,
     616             :         context,
     617             :         context_size,
     618             :         mapping_list_,
     619           0 :         *minidump_descriptor_.microdump_extra_info());
     620             :   }
     621           0 :   if (minidump_descriptor_.IsFD()) {
     622           0 :     return google_breakpad::WriteMinidump(minidump_descriptor_.fd(),
     623             :                                           minidump_descriptor_.size_limit(),
     624             :                                           crashing_process,
     625             :                                           context,
     626             :                                           context_size,
     627             :                                           mapping_list_,
     628           0 :                                           app_memory_list_);
     629             :   }
     630           0 :   return google_breakpad::WriteMinidump(minidump_descriptor_.path(),
     631             :                                         minidump_descriptor_.size_limit(),
     632             :                                         crashing_process,
     633             :                                         context,
     634             :                                         context_size,
     635             :                                         mapping_list_,
     636           0 :                                         app_memory_list_);
     637             : }
     638             : 
     639             : // static
     640           0 : bool ExceptionHandler::WriteMinidump(const string& dump_path,
     641             :                                      MinidumpCallback callback,
     642             :                                      void* callback_context) {
     643           0 :   MinidumpDescriptor descriptor(dump_path);
     644           0 :   ExceptionHandler eh(descriptor, NULL, callback, callback_context, false, -1);
     645           0 :   return eh.WriteMinidump();
     646             : }
     647             : 
     648             : // In order to making using EBP to calculate the desired value for ESP
     649             : // a valid operation, ensure that this function is compiled with a
     650             : // frame pointer using the following attribute. This attribute
     651             : // is supported on GCC but not on clang.
     652             : #if defined(__i386__) && defined(__GNUC__) && !defined(__clang__)
     653             : __attribute__((optimize("no-omit-frame-pointer")))
     654             : #endif
     655           0 : bool ExceptionHandler::WriteMinidump() {
     656           0 :   if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() &&
     657           0 :       !minidump_descriptor_.IsMicrodumpOnConsole()) {
     658             :     // Update the path of the minidump so that this can be called multiple times
     659             :     // and new files are created for each minidump.  This is done before the
     660             :     // generation happens, as clients may want to access the MinidumpDescriptor
     661             :     // after this call to find the exact path to the minidump file.
     662           0 :     minidump_descriptor_.UpdatePath();
     663           0 :   } else if (minidump_descriptor_.IsFD()) {
     664             :     // Reposition the FD to its beginning and resize it to get rid of the
     665             :     // previous minidump info.
     666           0 :     lseek(minidump_descriptor_.fd(), 0, SEEK_SET);
     667           0 :     ignore_result(ftruncate(minidump_descriptor_.fd(), 0));
     668             :   }
     669             : 
     670             :   // Allow this process to be dumped.
     671           0 :   sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
     672             : 
     673             :   CrashContext context;
     674           0 :   int getcontext_result = getcontext(&context.context);
     675           0 :   if (getcontext_result)
     676           0 :     return false;
     677             : 
     678             : #if defined(__i386__)
     679             :   // In CPUFillFromUContext in minidumpwriter.cc the stack pointer is retrieved
     680             :   // from REG_UESP instead of from REG_ESP. REG_UESP is the user stack pointer
     681             :   // and it only makes sense when running in kernel mode with a different stack
     682             :   // pointer. When WriteMiniDump is called during normal processing REG_UESP is
     683             :   // zero which leads to bad minidump files.
     684             :   if (!context.context.uc_mcontext.gregs[REG_UESP]) {
     685             :     // If REG_UESP is set to REG_ESP then that includes the stack space for the
     686             :     // CrashContext object in this function, which is about 128 KB. Since the
     687             :     // Linux dumper only records 32 KB of stack this would mean that nothing
     688             :     // useful would be recorded. A better option is to set REG_UESP to REG_EBP,
     689             :     // perhaps with a small negative offset in case there is any code that
     690             :     // objects to them being equal.
     691             :     context.context.uc_mcontext.gregs[REG_UESP] =
     692             :       context.context.uc_mcontext.gregs[REG_EBP] - 16;
     693             :     // The stack saving is based off of REG_ESP so it must be set to match the
     694             :     // new REG_UESP.
     695             :     context.context.uc_mcontext.gregs[REG_ESP] =
     696             :       context.context.uc_mcontext.gregs[REG_UESP];
     697             :   }
     698             : #endif
     699             : 
     700             : #if !defined(__ARM_EABI__) && !defined(__aarch64__) && !defined(__mips__)
     701             :   // FPU state is not part of ARM EABI ucontext_t.
     702           0 :   memcpy(&context.float_state, context.context.uc_mcontext.fpregs,
     703           0 :          sizeof(context.float_state));
     704             : #endif
     705           0 :   context.tid = sys_gettid();
     706             : 
     707             :   // Add an exception stream to the minidump for better reporting.
     708           0 :   memset(&context.siginfo, 0, sizeof(context.siginfo));
     709           0 :   context.siginfo.si_signo = MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED;
     710             : #if defined(__i386__)
     711             :   context.siginfo.si_addr =
     712             :       reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_EIP]);
     713             : #elif defined(__x86_64__)
     714           0 :   context.siginfo.si_addr =
     715           0 :       reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_RIP]);
     716             : #elif defined(__arm__)
     717             :   context.siginfo.si_addr =
     718             :       reinterpret_cast<void*>(context.context.uc_mcontext.arm_pc);
     719             : #elif defined(__aarch64__)
     720             :   context.siginfo.si_addr =
     721             :       reinterpret_cast<void*>(context.context.uc_mcontext.pc);
     722             : #elif defined(__mips__)
     723             :   context.siginfo.si_addr =
     724             :       reinterpret_cast<void*>(context.context.uc_mcontext.pc);
     725             : #else
     726             : #error "This code has not been ported to your platform yet."
     727             : #endif
     728             : 
     729           0 :   return GenerateDump(&context);
     730             : }
     731             : 
     732           0 : void ExceptionHandler::AddMappingInfo(const string& name,
     733             :                                       const uint8_t identifier[sizeof(MDGUID)],
     734             :                                       uintptr_t start_address,
     735             :                                       size_t mapping_size,
     736             :                                       size_t file_offset) {
     737             :   MappingInfo info;
     738           0 :   info.start_addr = start_address;
     739           0 :   info.size = mapping_size;
     740           0 :   info.offset = file_offset;
     741           0 :   strncpy(info.name, name.c_str(), sizeof(info.name) - 1);
     742           0 :   info.name[sizeof(info.name) - 1] = '\0';
     743             : 
     744             :   MappingEntry mapping;
     745           0 :   mapping.first = info;
     746           0 :   memcpy(mapping.second, identifier, sizeof(MDGUID));
     747           0 :   mapping_list_.push_back(mapping);
     748           0 : }
     749             : 
     750           0 : void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) {
     751             :   AppMemoryList::iterator iter =
     752           0 :     std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr);
     753           0 :   if (iter != app_memory_list_.end()) {
     754             :     // Don't allow registering the same pointer twice.
     755           0 :     return;
     756             :   }
     757             : 
     758             :   AppMemory app_memory;
     759           0 :   app_memory.ptr = ptr;
     760           0 :   app_memory.length = length;
     761           0 :   app_memory_list_.push_back(app_memory);
     762             : }
     763             : 
     764           0 : void ExceptionHandler::UnregisterAppMemory(void* ptr) {
     765             :   AppMemoryList::iterator iter =
     766           0 :     std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr);
     767           0 :   if (iter != app_memory_list_.end()) {
     768           0 :     app_memory_list_.erase(iter);
     769             :   }
     770           0 : }
     771             : 
     772             : // static
     773           0 : bool ExceptionHandler::WriteMinidumpForChild(pid_t child,
     774             :                                              pid_t child_blamed_thread,
     775             :                                              const string& dump_path,
     776             :                                              MinidumpCallback callback,
     777             :                                              void* callback_context) {
     778             :   // This function is not run in a compromised context.
     779           0 :   MinidumpDescriptor descriptor(dump_path);
     780           0 :   descriptor.UpdatePath();
     781           0 :   if (!google_breakpad::WriteMinidump(descriptor.path(),
     782             :                                       child,
     783             :                                       child_blamed_thread))
     784           0 :       return false;
     785             : 
     786           0 :   return callback ? callback(descriptor, callback_context, true) : true;
     787             : }
     788             : 
     789             : }  // namespace google_breakpad

Generated by: LCOV version 1.13