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 "client/linux/handler/exception_handler.h"
67 :
68 : #include <errno.h>
69 : #include <fcntl.h>
70 : #include <linux/limits.h>
71 : #include <sched.h>
72 : #include <signal.h>
73 : #include <stdio.h>
74 : #include <sys/mman.h>
75 : #include <sys/prctl.h>
76 : #if !defined(__ANDROID__)
77 : #include <sys/signal.h>
78 : #endif
79 : #include <sys/syscall.h>
80 : #if !defined(__ANDROID__)
81 : #include <sys/ucontext.h>
82 : #include <sys/user.h>
83 : #endif
84 : #include <sys/wait.h>
85 : #if !defined(__ANDROID__)
86 : #include <ucontext.h>
87 : #endif
88 : #include <unistd.h>
89 :
90 : #include <algorithm>
91 : #include <utility>
92 : #include <vector>
93 :
94 : #include "common/linux/linux_libc_support.h"
95 : #include "common/linux/linux_syscall_support.h"
96 : #include "common/memory.h"
97 : #include "client/linux/minidump_writer/linux_dumper.h"
98 : #include "client/linux/minidump_writer/minidump_writer.h"
99 : #include "common/linux/guid_creator.h"
100 : #include "common/linux/eintr_wrapper.h"
101 :
102 : #include "linux/sched.h"
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 : // The list of signals which we consider to be crashes. The default action for
117 : // all these signals must be Core (see man 7 signal) because we rethrow the
118 : // signal after handling it and expect that it'll be fatal.
119 : static const int kExceptionSignals[] = {
120 : SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1
121 : };
122 :
123 : // We can stack multiple exception handlers. In that case, this is the global
124 : // which holds the stack.
125 : std::vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
126 : unsigned ExceptionHandler::handler_stack_index_ = 0;
127 : pthread_mutex_t ExceptionHandler::handler_stack_mutex_ =
128 : PTHREAD_MUTEX_INITIALIZER;
129 :
130 : // Runs before crashing: normal context.
131 1408 : ExceptionHandler::ExceptionHandler(const std::string &dump_path,
132 : FilterCallback filter,
133 : MinidumpCallback callback,
134 : void *callback_context,
135 : bool install_handler)
136 : : filter_(filter),
137 : callback_(callback),
138 : callback_context_(callback_context),
139 1408 : handler_installed_(install_handler)
140 : {
141 1408 : Init(dump_path, -1);
142 1408 : }
143 :
144 1 : ExceptionHandler::ExceptionHandler(const std::string &dump_path,
145 : FilterCallback filter,
146 : MinidumpCallback callback,
147 : void* callback_context,
148 : bool install_handler,
149 : const int server_fd)
150 : : filter_(filter),
151 : callback_(callback),
152 : callback_context_(callback_context),
153 1 : handler_installed_(install_handler)
154 : {
155 1 : Init(dump_path, server_fd);
156 1 : }
157 :
158 : // Runs before crashing: normal context.
159 2772 : ExceptionHandler::~ExceptionHandler() {
160 1386 : UninstallHandlers();
161 1386 : }
162 :
163 1409 : void ExceptionHandler::Init(const std::string &dump_path,
164 : const int server_fd)
165 : {
166 1409 : crash_handler_ = NULL;
167 1409 : if (0 <= server_fd)
168 : crash_generation_client_
169 1 : .reset(CrashGenerationClient::TryCreate(server_fd));
170 :
171 1409 : if (handler_installed_)
172 1409 : InstallHandlers();
173 :
174 1409 : if (!IsOutOfProcess())
175 1408 : set_dump_path(dump_path);
176 :
177 1409 : pthread_mutex_lock(&handler_stack_mutex_);
178 1409 : if (handler_stack_ == NULL)
179 1409 : handler_stack_ = new std::vector<ExceptionHandler *>;
180 1409 : handler_stack_->push_back(this);
181 1409 : pthread_mutex_unlock(&handler_stack_mutex_);
182 1409 : }
183 :
184 : // Runs before crashing: normal context.
185 1409 : bool ExceptionHandler::InstallHandlers() {
186 : // We run the signal handlers on an alternative stack because we might have
187 : // crashed because of a stack overflow.
188 :
189 : // We use this value rather than SIGSTKSZ because we would end up overrunning
190 : // such a small stack.
191 : static const unsigned kSigStackSize = 8192;
192 :
193 : stack_t stack;
194 : // Only set an alternative stack if there isn't already one, or if the current
195 : // one is too small.
196 1409 : if (sys_sigaltstack(NULL, &stack) == -1 || !stack.ss_sp ||
197 : stack.ss_size < kSigStackSize) {
198 1409 : memset(&stack, 0, sizeof(stack));
199 1409 : stack.ss_sp = malloc(kSigStackSize);
200 1409 : stack.ss_size = kSigStackSize;
201 :
202 1409 : if (sys_sigaltstack(&stack, NULL) == -1)
203 0 : return false;
204 : }
205 :
206 : struct sigaction sa;
207 1409 : memset(&sa, 0, sizeof(sa));
208 1409 : sigemptyset(&sa.sa_mask);
209 :
210 : // mask all exception signals when we're handling one of them.
211 8454 : for (unsigned i = 0; kExceptionSignals[i] != -1; ++i)
212 7045 : sigaddset(&sa.sa_mask, kExceptionSignals[i]);
213 :
214 1409 : sa.sa_sigaction = SignalHandler;
215 1409 : sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
216 :
217 8454 : for (unsigned i = 0; kExceptionSignals[i] != -1; ++i) {
218 7045 : struct sigaction* old = new struct sigaction;
219 7045 : if (sigaction(kExceptionSignals[i], &sa, old) == -1)
220 0 : return false;
221 7045 : old_handlers_.push_back(std::make_pair(kExceptionSignals[i], old));
222 : }
223 1409 : return true;
224 : }
225 :
226 : // Runs before crashing: normal context.
227 1386 : void ExceptionHandler::UninstallHandlers() {
228 8316 : for (unsigned i = 0; i < old_handlers_.size(); ++i) {
229 : struct sigaction *action =
230 6930 : reinterpret_cast<struct sigaction*>(old_handlers_[i].second);
231 6930 : sigaction(old_handlers_[i].first, action, NULL);
232 : delete action;
233 : }
234 1386 : pthread_mutex_lock(&handler_stack_mutex_);
235 : std::vector<ExceptionHandler*>::iterator handler =
236 1386 : std::find(handler_stack_->begin(), handler_stack_->end(), this);
237 1386 : handler_stack_->erase(handler);
238 1386 : pthread_mutex_unlock(&handler_stack_mutex_);
239 1386 : old_handlers_.clear();
240 1386 : }
241 :
242 : // Runs before crashing: normal context.
243 2794 : void ExceptionHandler::UpdateNextID() {
244 : GUID guid;
245 : char guid_str[kGUIDStringLength + 1];
246 2794 : if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) {
247 2794 : next_minidump_id_ = guid_str;
248 2794 : next_minidump_id_c_ = next_minidump_id_.c_str();
249 :
250 : char minidump_path[PATH_MAX];
251 : snprintf(minidump_path, sizeof(minidump_path), "%s/%s.dmp",
252 : dump_path_c_,
253 2794 : guid_str);
254 :
255 2794 : next_minidump_path_ = minidump_path;
256 2794 : next_minidump_path_c_ = next_minidump_path_.c_str();
257 : }
258 2794 : }
259 :
260 : // void ExceptionHandler::set_crash_handler(HandlerCallback callback) {
261 : // crash_handler_ = callback;
262 : // }
263 :
264 : // This function runs in a compromised context: see the top of the file.
265 : // Runs on the crashing thread.
266 : // static
267 0 : void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
268 : // All the exception signals are blocked at this point.
269 0 : pthread_mutex_lock(&handler_stack_mutex_);
270 :
271 0 : if (!handler_stack_->size()) {
272 0 : pthread_mutex_unlock(&handler_stack_mutex_);
273 : return;
274 : }
275 :
276 0 : for (int i = handler_stack_->size() - 1; i >= 0; --i) {
277 0 : if ((*handler_stack_)[i]->HandleSignal(sig, info, uc)) {
278 : // successfully handled: We are in an invalid state since an exception
279 : // signal has been delivered. We don't call the exit handlers because
280 : // they could end up corrupting on-disk state.
281 0 : break;
282 : }
283 : }
284 :
285 0 : pthread_mutex_unlock(&handler_stack_mutex_);
286 :
287 : // Terminate ourselves with the same signal so that our parent knows that we
288 : // crashed. The default action for all the signals which we catch is Core, so
289 : // this is the end of us.
290 0 : signal(sig, SIG_DFL);
291 :
292 : // TODO(markus): mask signal and return to caller
293 0 : tgkill(getpid(), syscall(__NR_gettid), sig);
294 0 : _exit(1);
295 :
296 : // not reached.
297 : }
298 :
299 : struct ThreadArgument {
300 : pid_t pid; // the crashing process
301 : ExceptionHandler* handler;
302 : const void* context; // a CrashContext structure
303 : size_t context_size;
304 : };
305 :
306 : // This is the entry function for the cloned process. We are in a compromised
307 : // context here: see the top of the file.
308 : // static
309 0 : int ExceptionHandler::ThreadEntry(void *arg) {
310 0 : const ThreadArgument *thread_arg = reinterpret_cast<ThreadArgument*>(arg);
311 :
312 : // Block here until the crashing process unblocks us when
313 : // we're allowed to use ptrace
314 0 : thread_arg->handler->WaitForContinueSignal();
315 :
316 : return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context,
317 0 : thread_arg->context_size) == false;
318 : }
319 :
320 : // This function runs in a compromised context: see the top of the file.
321 : // Runs on the crashing thread.
322 0 : bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
323 0 : if (filter_ && !filter_(callback_context_))
324 0 : return false;
325 :
326 : // Allow ourselves to be dumped.
327 0 : sys_prctl(PR_SET_DUMPABLE, 1);
328 : CrashContext context;
329 0 : memcpy(&context.siginfo, info, sizeof(siginfo_t));
330 0 : memcpy(&context.context, uc, sizeof(struct ucontext));
331 : #if !defined(__ARM_EABI__)
332 : // FP state is not part of user ABI on ARM Linux.
333 0 : struct ucontext *uc_ptr = (struct ucontext*)uc;
334 0 : if (uc_ptr->uc_mcontext.fpregs) {
335 : memcpy(&context.float_state,
336 : uc_ptr->uc_mcontext.fpregs,
337 0 : sizeof(context.float_state));
338 : }
339 : #endif
340 0 : context.tid = syscall(__NR_gettid);
341 0 : if (crash_handler_ != NULL) {
342 0 : if (crash_handler_(&context, sizeof(context),
343 0 : callback_context_)) {
344 0 : return true;
345 : }
346 : }
347 0 : return GenerateDump(&context);
348 : }
349 :
350 : // This function may run in a compromised context: see the top of the file.
351 0 : bool ExceptionHandler::GenerateDump(CrashContext *context) {
352 0 : if (IsOutOfProcess())
353 0 : return crash_generation_client_->RequestDump(context, sizeof(*context));
354 :
355 : static const unsigned kChildStackSize = 8000;
356 0 : PageAllocator allocator;
357 0 : uint8_t* stack = (uint8_t*) allocator.Alloc(kChildStackSize);
358 0 : if (!stack)
359 0 : return false;
360 : // clone() needs the top-most address. (scrub just to be safe)
361 0 : stack += kChildStackSize;
362 0 : my_memset(stack - 16, 0, 16);
363 :
364 : ThreadArgument thread_arg;
365 0 : thread_arg.handler = this;
366 0 : thread_arg.pid = getpid();
367 0 : thread_arg.context = context;
368 0 : thread_arg.context_size = sizeof(*context);
369 :
370 : // We need to explicitly enable ptrace of parent processes on some
371 : // kernels, but we need to know the PID of the cloned process before we
372 : // can do this. Create a pipe here which we can use to block the
373 : // cloned process after creating it, until we have explicitly enabled ptrace
374 0 : if(sys_pipe(fdes) == -1) {
375 : // Creating the pipe failed. We'll log an error but carry on anyway,
376 : // as we'll probably still get a useful crash report. All that will happen
377 : // is the write() and read() calls will fail with EBADF
378 : static const char no_pipe_msg[] = "ExceptionHandler::GenerateDump \
379 : sys_pipe failed:";
380 0 : sys_write(2, no_pipe_msg, sizeof(no_pipe_msg) - 1);
381 0 : sys_write(2, strerror(errno), strlen(strerror(errno)));
382 0 : sys_write(2, "\n", 1);
383 : }
384 :
385 : const pid_t child = sys_clone(
386 : ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
387 0 : &thread_arg, NULL, NULL, NULL);
388 : int r, status;
389 : // Allow the child to ptrace us
390 0 : prctl(PR_SET_PTRACER, child, 0, 0, 0);
391 0 : SendContinueSignalToChild();
392 0 : do {
393 0 : r = sys_waitpid(child, &status, __WALL);
394 0 : } while (r == -1 && errno == EINTR);
395 :
396 0 : sys_close(fdes[0]);
397 0 : sys_close(fdes[1]);
398 :
399 0 : if (r == -1) {
400 : static const char msg[] = "ExceptionHandler::GenerateDump waitpid failed:";
401 0 : sys_write(2, msg, sizeof(msg) - 1);
402 0 : sys_write(2, strerror(errno), strlen(strerror(errno)));
403 0 : sys_write(2, "\n", 1);
404 : }
405 :
406 0 : bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0;
407 :
408 0 : if (callback_)
409 : success = callback_(dump_path_c_, next_minidump_id_c_,
410 0 : callback_context_, success);
411 :
412 0 : return success;
413 : }
414 :
415 : // This function runs in a compromised context: see the top of the file.
416 0 : void ExceptionHandler::SendContinueSignalToChild() {
417 : static const char okToContinueMessage = 'a';
418 : int r;
419 0 : r = HANDLE_EINTR(sys_write(fdes[1], &okToContinueMessage, sizeof(char)));
420 0 : if(r == -1) {
421 : static const char msg[] = "ExceptionHandler::SendContinueSignalToChild \
422 : sys_write failed:";
423 0 : sys_write(2, msg, sizeof(msg) - 1);
424 0 : sys_write(2, strerror(errno), strlen(strerror(errno)));
425 0 : sys_write(2, "\n", 1);
426 : }
427 0 : }
428 :
429 : // This function runs in a compromised context: see the top of the file.
430 : // Runs on the cloned process.
431 0 : void ExceptionHandler::WaitForContinueSignal() {
432 : int r;
433 : char receivedMessage;
434 0 : r = HANDLE_EINTR(sys_read(fdes[0], &receivedMessage, sizeof(char)));
435 0 : if(r == -1) {
436 : static const char msg[] = "ExceptionHandler::WaitForContinueSignal \
437 : sys_read failed:";
438 0 : sys_write(2, msg, sizeof(msg) - 1);
439 0 : sys_write(2, strerror(errno), strlen(strerror(errno)));
440 0 : sys_write(2, "\n", 1);
441 : }
442 0 : }
443 :
444 : // This function runs in a compromised context: see the top of the file.
445 : // Runs on the cloned process.
446 0 : bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
447 : size_t context_size) {
448 : return google_breakpad::WriteMinidump(next_minidump_path_c_,
449 : crashing_process,
450 : context,
451 : context_size,
452 : mapping_info_,
453 0 : app_memory_info_);
454 : }
455 :
456 : // static
457 0 : bool ExceptionHandler::WriteMinidump(const std::string &dump_path,
458 : MinidumpCallback callback,
459 : void* callback_context) {
460 0 : return WriteMinidump(dump_path, false, callback, callback_context);
461 : }
462 :
463 : // static
464 0 : bool ExceptionHandler::WriteMinidump(const std::string &dump_path,
465 : bool write_exception_stream,
466 : MinidumpCallback callback,
467 : void* callback_context) {
468 0 : ExceptionHandler eh(dump_path, NULL, callback, callback_context, false);
469 0 : return eh.WriteMinidump(write_exception_stream);
470 : }
471 :
472 0 : bool ExceptionHandler::WriteMinidump() {
473 0 : return WriteMinidump(false);
474 : }
475 :
476 0 : bool ExceptionHandler::WriteMinidump(bool write_exception_stream) {
477 : #if !defined(__ARM_EABI__)
478 : // Allow ourselves to be dumped.
479 0 : sys_prctl(PR_SET_DUMPABLE, 1);
480 :
481 : CrashContext context;
482 0 : int getcontext_result = getcontext(&context.context);
483 0 : if (getcontext_result)
484 0 : return false;
485 : memcpy(&context.float_state, context.context.uc_mcontext.fpregs,
486 0 : sizeof(context.float_state));
487 0 : context.tid = sys_gettid();
488 :
489 0 : if (write_exception_stream) {
490 0 : memset(&context.siginfo, 0, sizeof(context.siginfo));
491 0 : context.siginfo.si_signo = SIGSTOP;
492 : #if defined(__i386)
493 : context.siginfo.si_addr =
494 0 : reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_EIP]);
495 : #elif defined(__x86_64)
496 : context.siginfo.si_addr =
497 : reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_RIP]);
498 : #elif defined(__ARMEL__)
499 : context.siginfo.si_addr =
500 : reinterpret_cast<void*>(context.context.uc_mcontext.arm_ip);
501 : #endif
502 : }
503 :
504 0 : bool success = GenerateDump(&context);
505 0 : UpdateNextID();
506 0 : return success;
507 : #else
508 : return false;
509 : #endif // !defined(__ARM_EABI__)
510 : }
511 :
512 : // static
513 0 : bool ExceptionHandler::WriteMinidumpForChild(pid_t child,
514 : pid_t child_blamed_thread,
515 : const std::string &dump_path,
516 : MinidumpCallback callback,
517 : void *callback_context)
518 : {
519 : // This function is not run in a compromised context.
520 0 : ExceptionHandler eh(dump_path, NULL, NULL, NULL, false);
521 0 : if (!google_breakpad::WriteMinidump(eh.next_minidump_path_c_,
522 : child,
523 0 : child_blamed_thread))
524 0 : return false;
525 :
526 : return callback ? callback(eh.dump_path_c_, eh.next_minidump_id_c_,
527 0 : callback_context, true) : true;
528 : }
529 :
530 0 : void ExceptionHandler::AddMappingInfo(const std::string& name,
531 : const u_int8_t identifier[sizeof(MDGUID)],
532 : uintptr_t start_address,
533 : size_t mapping_size,
534 : size_t file_offset) {
535 : MappingInfo info;
536 0 : info.start_addr = start_address;
537 0 : info.size = mapping_size;
538 0 : info.offset = file_offset;
539 0 : strncpy(info.name, name.c_str(), std::min(name.size() + 1, sizeof(info)));
540 :
541 0 : std::pair<MappingInfo, u_int8_t[sizeof(MDGUID)]> mapping;
542 0 : mapping.first = info;
543 0 : memcpy(mapping.second, identifier, sizeof(MDGUID));
544 0 : mapping_info_.push_back(mapping);
545 0 : }
546 :
547 0 : void ExceptionHandler::RegisterAppMemory(void *ptr, size_t length) {
548 0 : app_memory_info_.push_back(AppMemory(ptr, length));
549 0 : }
550 :
551 0 : void ExceptionHandler::UnregisterAppMemory(void *ptr) {
552 0 : for (AppMemoryList::iterator iter = app_memory_info_.begin();
553 0 : iter != app_memory_info_.end();
554 : ++iter) {
555 0 : if (iter->ptr == ptr) {
556 0 : app_memory_info_.erase(iter);
557 0 : return;
558 : }
559 : }
560 : }
561 :
562 : } // namespace google_breakpad
|