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