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