| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #define SYS_SEGMENTNAME "syscalls" // For linux_syscall_support.h | 5 #define SYS_SEGMENTNAME "syscalls" // For linux_syscall_support.h |
| 6 | 6 |
| 7 #include "chrome/app/breakpad_linux.h" | 7 #include "chrome/app/breakpad_linux.h" |
| 8 | 8 |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <stdlib.h> | 10 #include <stdlib.h> |
| 11 #include <sys/socket.h> | 11 #include <sys/socket.h> |
| 12 #include <sys/time.h> | 12 #include <sys/time.h> |
| 13 #include <sys/types.h> | 13 #include <sys/types.h> |
| 14 #include <sys/uio.h> | 14 #include <sys/uio.h> |
| 15 #include <time.h> | 15 #include <time.h> |
| 16 #include <unistd.h> | 16 #include <unistd.h> |
| 17 | 17 |
| 18 #include <algorithm> | 18 #include <algorithm> |
| 19 #include <string> | 19 #include <string> |
| 20 | 20 |
| 21 #include "base/command_line.h" | 21 #include "base/command_line.h" |
| 22 #include "base/eintr_wrapper.h" | 22 #include "base/eintr_wrapper.h" |
| 23 #include "base/file_path.h" | 23 #include "base/file_path.h" |
| 24 #include "base/global_descriptors_posix.h" | 24 #include "base/global_descriptors_posix.h" |
| 25 #include "base/linux_util.h" |
| 25 #include "base/path_service.h" | 26 #include "base/path_service.h" |
| 26 #include "base/string_util.h" | 27 #include "base/string_util.h" |
| 27 #include "breakpad/src/client/linux/handler/exception_handler.h" | 28 #include "breakpad/src/client/linux/handler/exception_handler.h" |
| 28 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h" | 29 #include "breakpad/src/client/linux/minidump_writer/directory_reader.h" |
| 29 #include "breakpad/src/common/linux/linux_libc_support.h" | 30 #include "breakpad/src/common/linux/linux_libc_support.h" |
| 30 #include "breakpad/src/common/linux/linux_syscall_support.h" | 31 #include "breakpad/src/common/linux/linux_syscall_support.h" |
| 31 #include "breakpad/src/common/linux/memory.h" | 32 #include "breakpad/src/common/linux/memory.h" |
| 33 #include "chrome/common/child_process_logging.h" |
| 32 #include "chrome/common/chrome_descriptors.h" | 34 #include "chrome/common/chrome_descriptors.h" |
| 33 #include "chrome/common/chrome_paths.h" | 35 #include "chrome/common/chrome_paths.h" |
| 34 #include "chrome/common/chrome_switches.h" | 36 #include "chrome/common/chrome_switches.h" |
| 35 #include "chrome/common/chrome_version_info_posix.h" | 37 #include "chrome/common/chrome_version_info_posix.h" |
| 36 #include "chrome/common/env_vars.h" | 38 #include "chrome/common/env_vars.h" |
| 37 #include "chrome/installer/util/google_update_settings.h" | |
| 38 | 39 |
| 39 // Some versions of gcc are prone to warn about unused return values. In cases | 40 // Some versions of gcc are prone to warn about unused return values. In cases |
| 40 // where we either a) know the call cannot fail, or b) there is nothing we | 41 // where we either a) know the call cannot fail, or b) there is nothing we |
| 41 // can do when a call fails, we mark the return code as ignored. This avoids | 42 // can do when a call fails, we mark the return code as ignored. This avoids |
| 42 // spurious compiler warnings. | 43 // spurious compiler warnings. |
| 43 #define IGNORE_RET(x) do { if (x); } while (0) | 44 #define IGNORE_RET(x) do { if (x); } while (0) |
| 44 | 45 |
| 45 static const char kUploadURL[] = | 46 static const char kUploadURL[] = |
| 46 "https://clients2.google.com/cr/report"; | 47 "https://clients2.google.com/cr/report"; |
| 47 | 48 |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 static const char msg[] = "Cannot upload crash dump: cannot exec " | 573 static const char msg[] = "Cannot upload crash dump: cannot exec " |
| 573 "/usr/bin/wget\n"; | 574 "/usr/bin/wget\n"; |
| 574 sys_write(2, msg, sizeof(msg) - 1); | 575 sys_write(2, msg, sizeof(msg) - 1); |
| 575 sys__exit(1); | 576 sys__exit(1); |
| 576 } | 577 } |
| 577 | 578 |
| 578 HANDLE_EINTR(sys_waitpid(child, NULL, 0)); | 579 HANDLE_EINTR(sys_waitpid(child, NULL, 0)); |
| 579 return child; | 580 return child; |
| 580 } | 581 } |
| 581 | 582 |
| 582 // This is defined in chrome/browser/google_update_settings_posix.cc, it's the | |
| 583 // static string containing the user's unique GUID. We send this in the crash | |
| 584 // report. | |
| 585 namespace google_update { | |
| 586 extern std::string posix_guid; | |
| 587 } | |
| 588 | |
| 589 // This is defined in base/linux_util.cc, it's the static string containing the | |
| 590 // user's distro info. We send this in the crash report. | |
| 591 namespace base { | |
| 592 extern std::string linux_distro; | |
| 593 } | |
| 594 | |
| 595 static bool CrashDone(const char* dump_path, | 583 static bool CrashDone(const char* dump_path, |
| 596 const char* minidump_id, | 584 const char* minidump_id, |
| 597 const bool upload, | 585 const bool upload, |
| 598 const bool succeeded) { | 586 const bool succeeded) { |
| 599 // WARNING: this code runs in a compromised context. It may not call into | 587 // WARNING: this code runs in a compromised context. It may not call into |
| 600 // libc nor allocate memory normally. | 588 // libc nor allocate memory normally. |
| 601 if (!succeeded) | 589 if (!succeeded) |
| 602 return false; | 590 return false; |
| 603 | 591 |
| 604 google_breakpad::PageAllocator allocator; | 592 google_breakpad::PageAllocator allocator; |
| 605 const unsigned dump_path_len = my_strlen(dump_path); | 593 const unsigned dump_path_len = my_strlen(dump_path); |
| 606 const unsigned minidump_id_len = my_strlen(minidump_id); | 594 const unsigned minidump_id_len = my_strlen(minidump_id); |
| 607 char *const path = reinterpret_cast<char*>(allocator.Alloc( | 595 char *const path = reinterpret_cast<char*>(allocator.Alloc( |
| 608 dump_path_len + 1 /* '/' */ + minidump_id_len + | 596 dump_path_len + 1 /* '/' */ + minidump_id_len + |
| 609 4 /* ".dmp" */ + 1 /* NUL */)); | 597 4 /* ".dmp" */ + 1 /* NUL */)); |
| 610 memcpy(path, dump_path, dump_path_len); | 598 memcpy(path, dump_path, dump_path_len); |
| 611 path[dump_path_len] = '/'; | 599 path[dump_path_len] = '/'; |
| 612 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); | 600 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); |
| 613 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); | 601 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); |
| 614 path[dump_path_len + 1 + minidump_id_len + 4] = 0; | 602 path[dump_path_len + 1 + minidump_id_len + 4] = 0; |
| 615 | 603 |
| 616 BreakpadInfo info; | 604 BreakpadInfo info; |
| 617 info.filename = path; | 605 info.filename = path; |
| 618 info.process_type = "browser"; | 606 info.process_type = "browser"; |
| 619 info.process_type_length = 7; | 607 info.process_type_length = 7; |
| 620 info.crash_url = NULL; | 608 info.crash_url = NULL; |
| 621 info.crash_url_length = 0; | 609 info.crash_url_length = 0; |
| 622 info.guid = google_update::posix_guid.data(); | 610 info.guid = child_process_logging::g_client_id; |
| 623 info.guid_length = google_update::posix_guid.length(); | 611 info.guid_length = my_strlen(child_process_logging::g_client_id); |
| 624 info.distro = base::linux_distro.data(); | 612 info.distro = base::g_linux_distro; |
| 625 info.distro_length = base::linux_distro.length(); | 613 info.distro_length = my_strlen(base::g_linux_distro); |
| 626 info.upload = upload; | 614 info.upload = upload; |
| 627 HandleCrashDump(info); | 615 HandleCrashDump(info); |
| 628 | 616 |
| 629 return true; | 617 return true; |
| 630 } | 618 } |
| 631 | 619 |
| 632 // Wrapper script, do not add more code here. | 620 // Wrapper script, do not add more code here. |
| 633 static bool CrashDoneNoUpload(const char* dump_path, | 621 static bool CrashDoneNoUpload(const char* dump_path, |
| 634 const char* minidump_id, | 622 const char* minidump_id, |
| 635 void* context, | 623 void* context, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 652 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); | 640 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); |
| 653 new google_breakpad::ExceptionHandler(dumps_path.value().c_str(), NULL, | 641 new google_breakpad::ExceptionHandler(dumps_path.value().c_str(), NULL, |
| 654 CrashDoneNoUpload, NULL, | 642 CrashDoneNoUpload, NULL, |
| 655 true /* install handlers */); | 643 true /* install handlers */); |
| 656 } else { | 644 } else { |
| 657 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDoneUpload, NULL, | 645 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDoneUpload, NULL, |
| 658 true /* install handlers */); | 646 true /* install handlers */); |
| 659 } | 647 } |
| 660 } | 648 } |
| 661 | 649 |
| 662 // This is defined in chrome/common/child_process_logging_linux.cc, it's the | |
| 663 // static string containing the current active URL. We send this in the crash | |
| 664 // report. | |
| 665 namespace child_process_logging { | |
| 666 extern std::string active_url; | |
| 667 } | |
| 668 | |
| 669 // Currently Non-Browser = Renderer and Plugins | 650 // Currently Non-Browser = Renderer and Plugins |
| 670 static bool | 651 static bool |
| 671 NonBrowserCrashHandler(const void* crash_context, size_t crash_context_size, | 652 NonBrowserCrashHandler(const void* crash_context, size_t crash_context_size, |
| 672 void* context) { | 653 void* context) { |
| 673 const int fd = reinterpret_cast<intptr_t>(context); | 654 const int fd = reinterpret_cast<intptr_t>(context); |
| 674 int fds[2] = { -1, -1 }; | 655 int fds[2] = { -1, -1 }; |
| 675 if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { | 656 if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { |
| 676 static const char msg[] = "Failed to create socket for crash dumping.\n"; | 657 static const char msg[] = "Failed to create socket for crash dumping.\n"; |
| 677 sys_write(2, msg, sizeof(msg)-1); | 658 sys_write(2, msg, sizeof(msg)-1); |
| 678 return false; | 659 return false; |
| 679 } | 660 } |
| 680 char guid[kGuidSize + 1] = {0}; | 661 char guid[kGuidSize + 1] = {0}; |
| 681 char crash_url[kMaxActiveURLSize + 1] = {0}; | 662 char crash_url[kMaxActiveURLSize + 1] = {0}; |
| 682 char distro[kDistroSize + 1] = {0}; | 663 char distro[kDistroSize + 1] = {0}; |
| 683 const size_t guid_len = std::min(google_update::posix_guid.size(), | 664 const size_t guid_len = |
| 684 kGuidSize); | 665 std::min(my_strlen(child_process_logging::g_client_id), kGuidSize); |
| 685 const size_t crash_url_len = | 666 const size_t crash_url_len = |
| 686 std::min(child_process_logging::active_url.size(), kMaxActiveURLSize); | 667 std::min(my_strlen(child_process_logging::g_active_url), |
| 668 kMaxActiveURLSize); |
| 687 const size_t distro_len = | 669 const size_t distro_len = |
| 688 std::min(base::linux_distro.size(), kDistroSize); | 670 std::min(my_strlen(base::g_linux_distro), kDistroSize); |
| 689 memcpy(guid, google_update::posix_guid.data(), guid_len); | 671 memcpy(guid, child_process_logging::g_client_id, guid_len); |
| 690 memcpy(crash_url, child_process_logging::active_url.data(), crash_url_len); | 672 memcpy(crash_url, child_process_logging::g_active_url, crash_url_len); |
| 691 memcpy(distro, base::linux_distro.data(), distro_len); | 673 memcpy(distro, base::g_linux_distro, distro_len); |
| 692 | 674 |
| 693 char b; // Dummy variable for sys_read below. | 675 char b; // Dummy variable for sys_read below. |
| 694 const char* b_addr = &b; // Get the address of |b| so we can create the | 676 const char* b_addr = &b; // Get the address of |b| so we can create the |
| 695 // expected /proc/[pid]/syscall content in the | 677 // expected /proc/[pid]/syscall content in the |
| 696 // browser to convert namespace tids. | 678 // browser to convert namespace tids. |
| 697 | 679 |
| 698 // The length of the control message: | 680 // The length of the control message: |
| 699 static const unsigned kControlMsgSize = CMSG_SPACE(2*sizeof(int)); | 681 static const unsigned kControlMsgSize = CMSG_SPACE(2*sizeof(int)); |
| 700 | 682 |
| 701 struct kernel_msghdr msg; | 683 struct kernel_msghdr msg; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 // dir. Instead, we set a command line flag for these processes. | 751 // dir. Instead, we set a command line flag for these processes. |
| 770 // Even though plugins are not chrooted, we share the same code path for | 752 // Even though plugins are not chrooted, we share the same code path for |
| 771 // simplicity. | 753 // simplicity. |
| 772 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter)) | 754 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter)) |
| 773 return; | 755 return; |
| 774 // Get the guid and linux distro from the command line switch. | 756 // Get the guid and linux distro from the command line switch. |
| 775 std::string switch_value = | 757 std::string switch_value = |
| 776 parsed_command_line.GetSwitchValueASCII(switches::kEnableCrashReporter); | 758 parsed_command_line.GetSwitchValueASCII(switches::kEnableCrashReporter); |
| 777 size_t separator = switch_value.find(","); | 759 size_t separator = switch_value.find(","); |
| 778 if (separator != std::string::npos) { | 760 if (separator != std::string::npos) { |
| 779 google_update::posix_guid = switch_value.substr(0, separator); | 761 child_process_logging::SetClientId(switch_value.substr(0, separator)); |
| 780 base::linux_distro = switch_value.substr(separator + 1); | 762 base::SetLinuxDistro(switch_value.substr(separator + 1)); |
| 781 } else { | 763 } else { |
| 782 google_update::posix_guid = switch_value; | 764 child_process_logging::SetClientId(switch_value); |
| 783 } | 765 } |
| 784 EnableNonBrowserCrashDumping(); | 766 EnableNonBrowserCrashDumping(); |
| 785 } | 767 } |
| 786 | 768 |
| 787 // Set the base process uptime value. | 769 // Set the base process uptime value. |
| 788 struct timeval tv; | 770 struct timeval tv; |
| 789 if (!gettimeofday(&tv, NULL)) | 771 if (!gettimeofday(&tv, NULL)) |
| 790 uptime = timeval_to_ms(&tv); | 772 uptime = timeval_to_ms(&tv); |
| 791 else | 773 else |
| 792 uptime = 0; | 774 uptime = 0; |
| 793 } | 775 } |
| 794 | 776 |
| 795 bool IsCrashReporterEnabled() { | 777 bool IsCrashReporterEnabled() { |
| 796 return is_crash_reporter_enabled; | 778 return is_crash_reporter_enabled; |
| 797 } | 779 } |
| OLD | NEW |