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, ¤t_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