OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <unistd.h> | |
6 #include <fcntl.h> | 5 #include <fcntl.h> |
7 #include <sys/socket.h> | 6 #include <sys/socket.h> |
8 #include <sys/uio.h> | 7 #include <sys/uio.h> |
| 8 #include <unistd.h> |
9 | 9 |
| 10 #include <string> |
| 11 |
| 12 #include "base/command_line.h" |
10 #include "base/eintr_wrapper.h" | 13 #include "base/eintr_wrapper.h" |
| 14 #include "base/file_version_info_linux.h" |
| 15 #include "base/path_service.h" |
11 #include "base/rand_util.h" | 16 #include "base/rand_util.h" |
12 #include "base/file_version_info_linux.h" | |
13 #include "breakpad/linux/directory_reader.h" | 17 #include "breakpad/linux/directory_reader.h" |
14 #include "breakpad/linux/exception_handler.h" | 18 #include "breakpad/linux/exception_handler.h" |
15 #include "breakpad/linux/linux_libc_support.h" | 19 #include "breakpad/linux/linux_libc_support.h" |
16 #include "breakpad/linux/linux_syscall_support.h" | 20 #include "breakpad/linux/linux_syscall_support.h" |
17 #include "breakpad/linux/memory.h" | 21 #include "breakpad/linux/memory.h" |
| 22 #include "chrome/common/chrome_switches.h" |
| 23 #include "chrome/installer/util/google_update_settings.h" |
18 | 24 |
19 static const char kUploadURL[] = | 25 static const char kUploadURL[] = |
20 "https://clients2.google.com/cr/report"; | 26 "https://clients2.google.com/cr/report"; |
21 | 27 |
22 // Writes the value |v| as 16 hex characters to the memory pointed at by | 28 // Writes the value |v| as 16 hex characters to the memory pointed at by |
23 // |output|. | 29 // |output|. |
24 static void write_uint64_hex(char* output, uint64_t v) { | 30 static void write_uint64_hex(char* output, uint64_t v) { |
25 static const char hextable[] = "0123456789abcdef"; | 31 static const char hextable[] = "0123456789abcdef"; |
26 | 32 |
27 for (int i = 15; i >= 0; --i) { | 33 for (int i = 15; i >= 0; --i) { |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 kWgetBinary, | 348 kWgetBinary, |
343 header, | 349 header, |
344 post_file, | 350 post_file, |
345 kUploadURL, | 351 kUploadURL, |
346 "-O", // output reply to fd 3 | 352 "-O", // output reply to fd 3 |
347 "/dev/fd/3", | 353 "/dev/fd/3", |
348 NULL, | 354 NULL, |
349 }; | 355 }; |
350 | 356 |
351 execv("/usr/bin/wget", const_cast<char**>(args)); | 357 execv("/usr/bin/wget", const_cast<char**>(args)); |
352 static const char msg[] = "Cannot update crash dump: cannot exec " | 358 static const char msg[] = "Cannot upload crash dump: cannot exec " |
353 "/usr/bin/wget\n"; | 359 "/usr/bin/wget\n"; |
354 sys_write(2, msg, sizeof(msg) - 1); | 360 sys_write(2, msg, sizeof(msg) - 1); |
355 sys__exit(1); | 361 sys__exit(1); |
356 } | 362 } |
357 | 363 |
358 return child; | 364 return child; |
359 } | 365 } |
360 | 366 |
361 static bool CrashDone(const char* dump_path, | 367 static bool CrashDone(const char* dump_path, |
362 const char* minidump_id, | 368 const char* minidump_id, |
(...skipping 20 matching lines...) Expand all Loading... |
383 | 389 |
384 return true; | 390 return true; |
385 } | 391 } |
386 | 392 |
387 void EnableCrashDumping() { | 393 void EnableCrashDumping() { |
388 // We leak this object. | 394 // We leak this object. |
389 | 395 |
390 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDone, NULL, | 396 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDone, NULL, |
391 true /* install handlers */); | 397 true /* install handlers */); |
392 } | 398 } |
| 399 |
| 400 // This is defined in chrome/renderer/renderer_logging_linux.cc, it's the |
| 401 // static string containing the current active URL. We send this in the crash |
| 402 // report. |
| 403 namespace renderer_logging { |
| 404 extern std::string active_url; |
| 405 } |
| 406 |
| 407 static bool |
| 408 RendererCrashHandler(const void* crash_context, size_t crash_context_size, |
| 409 void* context) { |
| 410 const int fd = (int) context; |
| 411 int fds[2]; |
| 412 pipe(fds); |
| 413 |
| 414 // The length of the control message: |
| 415 static const unsigned kControlMsgSize = |
| 416 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); |
| 417 |
| 418 union { |
| 419 struct kernel_msghdr msg; |
| 420 struct msghdr sys_msg; |
| 421 }; |
| 422 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
| 423 struct kernel_iovec iov[2]; |
| 424 iov[0].iov_base = const_cast<void*>(crash_context); |
| 425 iov[0].iov_len = crash_context_size; |
| 426 iov[1].iov_base = const_cast<char*>(renderer_logging::active_url.data()); |
| 427 iov[1].iov_len = renderer_logging::active_url.size(); |
| 428 |
| 429 msg.msg_iov = iov; |
| 430 msg.msg_iovlen = 2; |
| 431 char cmsg[kControlMsgSize]; |
| 432 memset(cmsg, 0, kControlMsgSize); |
| 433 msg.msg_control = cmsg; |
| 434 msg.msg_controllen = sizeof(cmsg); |
| 435 |
| 436 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); |
| 437 hdr->cmsg_level = SOL_SOCKET; |
| 438 hdr->cmsg_type = SCM_RIGHTS; |
| 439 hdr->cmsg_len = CMSG_LEN(sizeof(int)); |
| 440 *((int*) CMSG_DATA(hdr)) = fds[1]; |
| 441 hdr = CMSG_NXTHDR(&sys_msg, hdr); |
| 442 hdr->cmsg_level = SOL_SOCKET; |
| 443 hdr->cmsg_type = SCM_CREDENTIALS; |
| 444 hdr->cmsg_len = CMSG_LEN(sizeof(struct ucred)); |
| 445 struct ucred *cred = reinterpret_cast<struct ucred*>(CMSG_DATA(hdr)); |
| 446 cred->uid = getuid(); |
| 447 cred->gid = getgid(); |
| 448 cred->pid = getpid(); |
| 449 |
| 450 HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)); |
| 451 sys_close(fds[1]); |
| 452 |
| 453 char b; |
| 454 HANDLE_EINTR(sys_read(fds[0], &b, 1)); |
| 455 |
| 456 return true; |
| 457 } |
| 458 |
| 459 void EnableRendererCrashDumping() { |
| 460 // When the browser forks off our process, it installs the crash signal file |
| 461 // descriptor in this slot: |
| 462 static const int kMagicCrashSignalFd = 4; |
| 463 |
| 464 // We deliberately leak this object. |
| 465 google_breakpad::ExceptionHandler* handler = |
| 466 new google_breakpad::ExceptionHandler("" /* unused */, NULL, NULL, |
| 467 (void*) kMagicCrashSignalFd, true); |
| 468 handler->set_crash_handler(RendererCrashHandler); |
| 469 } |
| 470 |
| 471 void InitCrashReporter() { |
| 472 if (!GoogleUpdateSettings::GetCollectStatsConsent()) |
| 473 return; |
| 474 |
| 475 // Determine the process type and take appropriate action. |
| 476 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); |
| 477 const std::wstring process_type = |
| 478 parsed_command_line.GetSwitchValue(switches::kProcessType); |
| 479 if (process_type.empty()) |
| 480 EnableCrashDumping(); |
| 481 else if (process_type == switches::kRendererProcess) |
| 482 EnableRendererCrashDumping(); |
| 483 } |
OLD | NEW |