OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // For linux_syscall_support.h. This makes it safe to call embedded system | 5 // For linux_syscall_support.h. This makes it safe to call embedded system |
6 // calls when in seccomp mode. | 6 // calls when in seccomp mode. |
7 #define SYS_SYSCALL_ENTRYPOINT "playground$syscallEntryPoint" | 7 #define SYS_SYSCALL_ENTRYPOINT "playground$syscallEntryPoint" |
8 | 8 |
9 #include "chrome/app/breakpad_linux.h" | 9 #include "chrome/app/breakpad_linux.h" |
10 | 10 |
11 #include <fcntl.h> | 11 #include <fcntl.h> |
(...skipping 20 matching lines...) Expand all Loading... |
32 #include "breakpad/src/common/linux/linux_libc_support.h" | 32 #include "breakpad/src/common/linux/linux_libc_support.h" |
33 #include "breakpad/src/common/memory.h" | 33 #include "breakpad/src/common/memory.h" |
34 #include "chrome/common/child_process_logging.h" | 34 #include "chrome/common/child_process_logging.h" |
35 #include "chrome/common/chrome_paths.h" | 35 #include "chrome/common/chrome_paths.h" |
36 #include "chrome/common/chrome_switches.h" | 36 #include "chrome/common/chrome_switches.h" |
37 #include "chrome/common/chrome_version_info_posix.h" | 37 #include "chrome/common/chrome_version_info_posix.h" |
38 #include "chrome/common/env_vars.h" | 38 #include "chrome/common/env_vars.h" |
39 #include "content/common/chrome_descriptors.h" | 39 #include "content/common/chrome_descriptors.h" |
40 #include "seccompsandbox/linux_syscall_support.h" | 40 #include "seccompsandbox/linux_syscall_support.h" |
41 | 41 |
| 42 #ifndef PR_SET_PTRACER |
| 43 #define PR_SET_PTRACER 0x59616d61 |
| 44 #endif |
| 45 |
42 // Some versions of gcc are prone to warn about unused return values. In cases | 46 // Some versions of gcc are prone to warn about unused return values. In cases |
43 // where we either a) know the call cannot fail, or b) there is nothing we | 47 // where we either a) know the call cannot fail, or b) there is nothing we |
44 // can do when a call fails, we mark the return code as ignored. This avoids | 48 // can do when a call fails, we mark the return code as ignored. This avoids |
45 // spurious compiler warnings. | 49 // spurious compiler warnings. |
46 #define IGNORE_RET(x) do { if (x); } while (0) | 50 #define IGNORE_RET(x) do { if (x); } while (0) |
47 | 51 |
48 static const char kUploadURL[] = | 52 static const char kUploadURL[] = |
49 "https://clients2.google.com/cr/report"; | 53 "https://clients2.google.com/cr/report"; |
50 | 54 |
51 static bool is_crash_reporter_enabled = false; | 55 static bool is_crash_reporter_enabled = false; |
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 const bool upload, | 718 const bool upload, |
715 const bool succeeded) { | 719 const bool succeeded) { |
716 // WARNING: this code runs in a compromised context. It may not call into | 720 // WARNING: this code runs in a compromised context. It may not call into |
717 // libc nor allocate memory normally. | 721 // libc nor allocate memory normally. |
718 if (!succeeded) | 722 if (!succeeded) |
719 return false; | 723 return false; |
720 | 724 |
721 google_breakpad::PageAllocator allocator; | 725 google_breakpad::PageAllocator allocator; |
722 const unsigned dump_path_len = my_strlen(dump_path); | 726 const unsigned dump_path_len = my_strlen(dump_path); |
723 const unsigned minidump_id_len = my_strlen(minidump_id); | 727 const unsigned minidump_id_len = my_strlen(minidump_id); |
724 char *const path = reinterpret_cast<char*>(allocator.Alloc( | 728 char* const path = reinterpret_cast<char*>(allocator.Alloc( |
725 dump_path_len + 1 /* '/' */ + minidump_id_len + | 729 dump_path_len + 1 /* '/' */ + minidump_id_len + |
726 4 /* ".dmp" */ + 1 /* NUL */)); | 730 4 /* ".dmp" */ + 1 /* NUL */)); |
727 memcpy(path, dump_path, dump_path_len); | 731 memcpy(path, dump_path, dump_path_len); |
728 path[dump_path_len] = '/'; | 732 path[dump_path_len] = '/'; |
729 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); | 733 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); |
730 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); | 734 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); |
731 path[dump_path_len + 1 + minidump_id_len + 4] = 0; | 735 path[dump_path_len + 1 + minidump_id_len + 4] = 0; |
732 | 736 |
733 BreakpadInfo info; | 737 BreakpadInfo info; |
734 info.filename = path; | 738 info.filename = path; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 CrashDoneNoUpload, NULL, | 787 CrashDoneNoUpload, NULL, |
784 true /* install handlers */); | 788 true /* install handlers */); |
785 } else { | 789 } else { |
786 new google_breakpad::ExceptionHandler(tmp_path.value().c_str(), NULL, | 790 new google_breakpad::ExceptionHandler(tmp_path.value().c_str(), NULL, |
787 CrashDoneUpload, NULL, | 791 CrashDoneUpload, NULL, |
788 true /* install handlers */); | 792 true /* install handlers */); |
789 } | 793 } |
790 } | 794 } |
791 | 795 |
792 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer | 796 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer |
793 static bool | 797 static bool NonBrowserCrashHandler(const void* crash_context, |
794 NonBrowserCrashHandler(const void* crash_context, size_t crash_context_size, | 798 size_t crash_context_size, |
795 void* context) { | 799 void* context) { |
796 const int fd = reinterpret_cast<intptr_t>(context); | 800 const int fd = reinterpret_cast<intptr_t>(context); |
797 int fds[2] = { -1, -1 }; | 801 int fds[2] = { -1, -1 }; |
798 if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { | 802 if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { |
799 static const char msg[] = "Failed to create socket for crash dumping.\n"; | 803 static const char msg[] = "Failed to create socket for crash dumping.\n"; |
800 sys_write(2, msg, sizeof(msg)-1); | 804 sys_write(2, msg, sizeof(msg)-1); |
801 return false; | 805 return false; |
802 } | 806 } |
| 807 |
| 808 // On kernels with ptrace protection, e.g. Ubuntu 10.10+, the browser cannot |
| 809 // ptrace this crashing process and crash dumping will fail. When using the |
| 810 // SUID sandbox, this crashing process is likely to be in its own PID |
| 811 // namespace, and thus there is no way to permit only the browser process to |
| 812 // ptrace it. |
| 813 // The workaround is to allow all processes to ptrace this process if we |
| 814 // reach this point, by passing -1 as the allowed PID. However, support for |
| 815 // passing -1 as the PID won't reach kernels until around the Ubuntu 12.04 |
| 816 // timeframe. |
| 817 sys_prctl(PR_SET_PTRACER, -1); |
| 818 |
| 819 // Start constructing the message to send to the browser. |
803 char guid[kGuidSize + 1] = {0}; | 820 char guid[kGuidSize + 1] = {0}; |
804 char crash_url[kMaxActiveURLSize + 1] = {0}; | 821 char crash_url[kMaxActiveURLSize + 1] = {0}; |
805 char distro[kDistroSize + 1] = {0}; | 822 char distro[kDistroSize + 1] = {0}; |
806 const size_t guid_len = | 823 const size_t guid_len = |
807 std::min(my_strlen(child_process_logging::g_client_id), kGuidSize); | 824 std::min(my_strlen(child_process_logging::g_client_id), kGuidSize); |
808 const size_t crash_url_len = | 825 const size_t crash_url_len = |
809 std::min(my_strlen(child_process_logging::g_active_url), | 826 std::min(my_strlen(child_process_logging::g_active_url), |
810 kMaxActiveURLSize); | 827 kMaxActiveURLSize); |
811 const size_t distro_len = | 828 const size_t distro_len = |
812 std::min(my_strlen(base::g_linux_distro), kDistroSize); | 829 std::min(my_strlen(base::g_linux_distro), kDistroSize); |
813 memcpy(guid, child_process_logging::g_client_id, guid_len); | 830 memcpy(guid, child_process_logging::g_client_id, guid_len); |
814 memcpy(crash_url, child_process_logging::g_active_url, crash_url_len); | 831 memcpy(crash_url, child_process_logging::g_active_url, crash_url_len); |
815 memcpy(distro, base::g_linux_distro, distro_len); | 832 memcpy(distro, base::g_linux_distro, distro_len); |
816 | 833 |
817 char b; // Dummy variable for sys_read below. | 834 char b; // Dummy variable for sys_read below. |
818 const char* b_addr = &b; // Get the address of |b| so we can create the | 835 const char* b_addr = &b; // Get the address of |b| so we can create the |
819 // expected /proc/[pid]/syscall content in the | 836 // expected /proc/[pid]/syscall content in the |
820 // browser to convert namespace tids. | 837 // browser to convert namespace tids. |
821 | 838 |
822 // The length of the control message: | 839 // The length of the control message: |
823 static const unsigned kControlMsgSize = CMSG_SPACE(2*sizeof(int)); | 840 static const unsigned kControlMsgSize = sizeof(fds); |
| 841 static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize); |
| 842 static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize); |
824 | 843 |
825 const size_t kIovSize = 7; | 844 const size_t kIovSize = 7; |
826 struct kernel_msghdr msg; | 845 struct kernel_msghdr msg; |
827 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); | 846 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
828 struct kernel_iovec iov[kIovSize]; | 847 struct kernel_iovec iov[kIovSize]; |
829 iov[0].iov_base = const_cast<void*>(crash_context); | 848 iov[0].iov_base = const_cast<void*>(crash_context); |
830 iov[0].iov_len = crash_context_size; | 849 iov[0].iov_len = crash_context_size; |
831 iov[1].iov_base = guid; | 850 iov[1].iov_base = guid; |
832 iov[1].iov_len = kGuidSize + 1; | 851 iov[1].iov_len = kGuidSize + 1; |
833 iov[2].iov_base = crash_url; | 852 iov[2].iov_base = crash_url; |
834 iov[2].iov_len = kMaxActiveURLSize + 1; | 853 iov[2].iov_len = kMaxActiveURLSize + 1; |
835 iov[3].iov_base = distro; | 854 iov[3].iov_base = distro; |
836 iov[3].iov_len = kDistroSize + 1; | 855 iov[3].iov_len = kDistroSize + 1; |
837 iov[4].iov_base = &b_addr; | 856 iov[4].iov_base = &b_addr; |
838 iov[4].iov_len = sizeof(b_addr); | 857 iov[4].iov_len = sizeof(b_addr); |
839 iov[5].iov_base = &fds[0]; | 858 iov[5].iov_base = &fds[0]; |
840 iov[5].iov_len = sizeof(fds[0]); | 859 iov[5].iov_len = sizeof(fds[0]); |
841 iov[6].iov_base = &process_start_time; | 860 iov[6].iov_base = &process_start_time; |
842 iov[6].iov_len = sizeof(process_start_time); | 861 iov[6].iov_len = sizeof(process_start_time); |
843 | 862 |
844 msg.msg_iov = iov; | 863 msg.msg_iov = iov; |
845 msg.msg_iovlen = kIovSize; | 864 msg.msg_iovlen = kIovSize; |
846 char cmsg[kControlMsgSize]; | 865 char cmsg[kControlMsgSpaceSize]; |
847 my_memset(cmsg, 0, kControlMsgSize); | 866 my_memset(cmsg, 0, kControlMsgSpaceSize); |
848 msg.msg_control = cmsg; | 867 msg.msg_control = cmsg; |
849 msg.msg_controllen = sizeof(cmsg); | 868 msg.msg_controllen = sizeof(cmsg); |
850 | 869 |
851 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); | 870 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); |
852 hdr->cmsg_level = SOL_SOCKET; | 871 hdr->cmsg_level = SOL_SOCKET; |
853 hdr->cmsg_type = SCM_RIGHTS; | 872 hdr->cmsg_type = SCM_RIGHTS; |
854 hdr->cmsg_len = CMSG_LEN(2*sizeof(int)); | 873 hdr->cmsg_len = kControlMsgLenSize; |
855 ((int*) CMSG_DATA(hdr))[0] = fds[0]; | 874 ((int*) CMSG_DATA(hdr))[0] = fds[0]; |
856 ((int*) CMSG_DATA(hdr))[1] = fds[1]; | 875 ((int*) CMSG_DATA(hdr))[1] = fds[1]; |
857 | 876 |
858 if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) { | 877 if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) { |
859 static const char msg[] = "Failed to tell parent about crash.\n"; | 878 static const char msg[] = "Failed to tell parent about crash.\n"; |
860 sys_write(2, msg, sizeof(msg)-1); | 879 sys_write(2, msg, sizeof(msg)-1); |
861 IGNORE_RET(sys_close(fds[1])); | 880 IGNORE_RET(sys_close(fds[1])); |
862 return false; | 881 return false; |
863 } | 882 } |
864 IGNORE_RET(sys_close(fds[1])); | 883 IGNORE_RET(sys_close(fds[1])); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 struct timeval tv; | 939 struct timeval tv; |
921 if (!gettimeofday(&tv, NULL)) | 940 if (!gettimeofday(&tv, NULL)) |
922 process_start_time = timeval_to_ms(&tv); | 941 process_start_time = timeval_to_ms(&tv); |
923 else | 942 else |
924 process_start_time = 0; | 943 process_start_time = 0; |
925 } | 944 } |
926 | 945 |
927 bool IsCrashReporterEnabled() { | 946 bool IsCrashReporterEnabled() { |
928 return is_crash_reporter_enabled; | 947 return is_crash_reporter_enabled; |
929 } | 948 } |
OLD | NEW |