| Index: chrome/app/breakpad_linux.cc
|
| ===================================================================
|
| --- chrome/app/breakpad_linux.cc (revision 20935)
|
| +++ chrome/app/breakpad_linux.cc (working copy)
|
| @@ -16,6 +16,7 @@
|
| #include "base/eintr_wrapper.h"
|
| #include "base/file_version_info_linux.h"
|
| #include "base/global_descriptors_posix.h"
|
| +#include "base/linux_util.h"
|
| #include "base/path_service.h"
|
| #include "base/rand_util.h"
|
| #include "base/string_util.h"
|
| @@ -42,17 +43,11 @@
|
| }
|
| }
|
|
|
| -pid_t UploadCrashDump(const char* filename,
|
| - const char* process_type,
|
| - unsigned process_type_length,
|
| - const char* crash_url,
|
| - unsigned crash_url_length,
|
| - const char* guid,
|
| - unsigned guid_length) {
|
| +pid_t UploadCrashDump(const BreakpadInfo& info) {
|
| // WARNING: this code runs in a compromised context. It may not call into
|
| // libc nor allocate memory normally.
|
|
|
| - const int dumpfd = sys_open(filename, O_RDONLY, 0);
|
| + const int dumpfd = sys_open(info.filename, O_RDONLY, 0);
|
| if (dumpfd < 0) {
|
| static const char msg[] = "Cannot upload crash dump: failed to open\n";
|
| sys_write(2, msg, sizeof(msg));
|
| @@ -144,6 +139,16 @@
|
| // BOUNDARY \r\n (27, 28)
|
| //
|
| // zero or more:
|
| + // Content-Disposition: form-data; name="ptype" \r\n \r\n (0..4)
|
| + // abcdef \r\n (5, 6)
|
| + // BOUNDARY \r\n (7, 8)
|
| + //
|
| + // zero or more:
|
| + // Content-Disposition: form-data; name="lsb-release" \r\n \r\n (0..4)
|
| + // abcdef \r\n (5, 6)
|
| + // BOUNDARY \r\n (7, 8)
|
| + //
|
| + // zero or more:
|
| // Content-Disposition: form-data; name="url-chunk-1" \r\n \r\n (0..5)
|
| // abcdef \r\n (6, 7)
|
| // BOUNDARY \r\n (8, 9)
|
| @@ -166,6 +171,7 @@
|
| "Content-Type: application/octet-stream";
|
| static const char url_chunk_msg[] = "url-chunk-";
|
| static const char process_type_msg[] = "ptype";
|
| + static const char distro_msg[] = "lsb-release";
|
|
|
| struct kernel_iovec iov[29];
|
| iov[0].iov_base = mime_boundary;
|
| @@ -226,8 +232,8 @@
|
| iov[24].iov_base = const_cast<char*>(rn);
|
| iov[24].iov_len = sizeof(rn);
|
|
|
| - iov[25].iov_base = const_cast<char*>(guid);
|
| - iov[25].iov_len = guid_length;
|
| + iov[25].iov_base = const_cast<char*>(info.guid);
|
| + iov[25].iov_len = info.guid_length;
|
| iov[26].iov_base = const_cast<char*>(rn);
|
| iov[26].iov_len = sizeof(rn);
|
|
|
| @@ -238,7 +244,7 @@
|
|
|
| sys_writev(fd, iov, 29);
|
|
|
| - if (process_type_length) {
|
| + if (info.process_type_length) {
|
| iov[0].iov_base = const_cast<char*>(form_data_msg);
|
| iov[0].iov_len = sizeof(form_data_msg) - 1;
|
| iov[1].iov_base = const_cast<char*>(process_type_msg);
|
| @@ -250,8 +256,8 @@
|
| iov[4].iov_base = const_cast<char*>(rn);
|
| iov[4].iov_len = sizeof(rn);
|
|
|
| - iov[5].iov_base = const_cast<char*>(process_type);
|
| - iov[5].iov_len = process_type_length;
|
| + iov[5].iov_base = const_cast<char*>(info.process_type);
|
| + iov[5].iov_len = info.process_type_length;
|
| iov[6].iov_base = const_cast<char*>(rn);
|
| iov[6].iov_len = sizeof(rn);
|
| iov[7].iov_base = mime_boundary;
|
| @@ -262,8 +268,32 @@
|
| sys_writev(fd, iov, 9);
|
| }
|
|
|
| - if (crash_url_length) {
|
| - unsigned i = 0, done = 0;
|
| + if (info.distro_length) {
|
| + iov[0].iov_base = const_cast<char*>(form_data_msg);
|
| + iov[0].iov_len = sizeof(form_data_msg) - 1;
|
| + iov[1].iov_base = const_cast<char*>(distro_msg);
|
| + iov[1].iov_len = sizeof(distro_msg) - 1;
|
| + iov[2].iov_base = const_cast<char*>(quote_msg);
|
| + iov[2].iov_len = sizeof(quote_msg);
|
| + iov[3].iov_base = const_cast<char*>(rn);
|
| + iov[3].iov_len = sizeof(rn);
|
| + iov[4].iov_base = const_cast<char*>(rn);
|
| + iov[4].iov_len = sizeof(rn);
|
| +
|
| + iov[5].iov_base = const_cast<char*>(info.distro);
|
| + iov[5].iov_len = info.distro_length;
|
| + iov[6].iov_base = const_cast<char*>(rn);
|
| + iov[6].iov_len = sizeof(rn);
|
| + iov[7].iov_base = mime_boundary;
|
| + iov[7].iov_len = sizeof(mime_boundary) - 1;
|
| + iov[8].iov_base = const_cast<char*>(rn);
|
| + iov[8].iov_len = sizeof(rn);
|
| +
|
| + sys_writev(fd, iov, 9);
|
| + }
|
| +
|
| + if (info.crash_url_length) {
|
| + unsigned i = 0, done = 0, crash_url_length = info.crash_url_length;
|
| static const unsigned kMaxCrashChunkSize = 64;
|
| static const unsigned kMaxUrlLength = 8 * kMaxCrashChunkSize;
|
| if (crash_url_length > kMaxUrlLength)
|
| @@ -289,7 +319,7 @@
|
|
|
| const unsigned len = crash_url_length > kMaxCrashChunkSize ?
|
| kMaxCrashChunkSize : crash_url_length;
|
| - iov[6].iov_base = const_cast<char*>(crash_url + done);
|
| + iov[6].iov_base = const_cast<char*>(info.crash_url + done);
|
| iov[6].iov_len = len;
|
| iov[7].iov_base = const_cast<char*>(rn);
|
| iov[7].iov_len = sizeof(rn);
|
| @@ -402,7 +432,7 @@
|
| sys_write(2, id_buf, my_strlen(id_buf));
|
| sys_write(2, "\n", 1);
|
| }
|
| - sys_unlink(filename);
|
| + sys_unlink(info.filename);
|
| sys_unlink(buf);
|
| sys__exit(0);
|
| }
|
| @@ -437,6 +467,12 @@
|
| extern std::string linux_guid;
|
| }
|
|
|
| +// This is defined in base/linux_util.cc, it's the static string containing the
|
| +// user's distro info. We send this in the crash report.
|
| +namespace base {
|
| +extern std::string linux_distro;
|
| +}
|
| +
|
| static bool CrashDone(const char* dump_path,
|
| const char* minidump_id,
|
| void* context,
|
| @@ -458,8 +494,17 @@
|
| memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4);
|
| path[dump_path_len + 1 + minidump_id_len + 4] = 0;
|
|
|
| - UploadCrashDump(path, "browser", 7, NULL, 0, google_update::linux_guid.data(),
|
| - google_update::linux_guid.length());
|
| + BreakpadInfo info;
|
| + info.filename = path;
|
| + info.process_type = "browser";
|
| + info.process_type_length = 7;
|
| + info.crash_url = NULL;
|
| + info.crash_url_length = 0;
|
| + info.guid = google_update::linux_guid.data();
|
| + info.guid_length = google_update::linux_guid.length();
|
| + info.distro = base::linux_distro.data();
|
| + info.distro_length = base::linux_distro.length();
|
| + UploadCrashDump(info);
|
|
|
| return true;
|
| }
|
| @@ -481,33 +526,39 @@
|
| static bool
|
| RendererCrashHandler(const void* crash_context, size_t crash_context_size,
|
| void* context) {
|
| - const int fd = (int) context;
|
| + const int fd = reinterpret_cast<int>(context);
|
| int fds[2];
|
| socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
|
| char guid[kGuidSize] = {0};
|
| char crash_url[kMaxActiveURLSize + 1] = {0};
|
| + char distro[kDistroSize + 1] = {0};
|
| const unsigned guid_len = std::min(google_update::linux_guid.size(),
|
| kGuidSize);
|
| const unsigned crash_url_len =
|
| std::min(child_process_logging::active_url.size(), kMaxActiveURLSize);
|
| + const unsigned distro_len =
|
| + std::min(base::linux_distro.size(), kDistroSize);
|
| memcpy(guid, google_update::linux_guid.data(), guid_len);
|
| memcpy(crash_url, child_process_logging::active_url.data(), crash_url_len);
|
| + memcpy(distro, base::linux_distro.data(), distro_len);
|
|
|
| // The length of the control message:
|
| static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int));
|
|
|
| struct kernel_msghdr msg;
|
| my_memset(&msg, 0, sizeof(struct kernel_msghdr));
|
| - struct kernel_iovec iov[3];
|
| + struct kernel_iovec iov[4];
|
| iov[0].iov_base = const_cast<void*>(crash_context);
|
| iov[0].iov_len = crash_context_size;
|
| iov[1].iov_base = guid;
|
| iov[1].iov_len = kGuidSize + 1;
|
| iov[2].iov_base = crash_url;
|
| iov[2].iov_len = kMaxActiveURLSize + 1;
|
| + iov[3].iov_base = distro;
|
| + iov[3].iov_len = kDistroSize + 1;
|
|
|
| msg.msg_iov = iov;
|
| - msg.msg_iovlen = 3;
|
| + msg.msg_iovlen = 4;
|
| char cmsg[kControlMsgSize];
|
| memset(cmsg, 0, kControlMsgSize);
|
| msg.msg_control = cmsg;
|
| @@ -545,6 +596,7 @@
|
| if (process_type.empty()) {
|
| if (!GoogleUpdateSettings::GetCollectStatsConsent())
|
| return;
|
| + base::GetLinuxDistro(); // Initialize base::linux_distro if needed.
|
| EnableCrashDumping();
|
| } else if (process_type == switches::kRendererProcess ||
|
| process_type == switches::kZygoteProcess) {
|
| @@ -553,8 +605,16 @@
|
| // dir. Instead, we set a command line flag for these processes.
|
| if (!parsed_command_line.HasSwitch(switches::kRendererCrashDump))
|
| return;
|
| - google_update::linux_guid = WideToASCII(
|
| + // Get the guid and linux distro from the command line switch.
|
| + std::string switch_value = WideToASCII(
|
| parsed_command_line.GetSwitchValue(switches::kRendererCrashDump));
|
| + size_t separator = switch_value.find(",");
|
| + if (separator != std::string::npos) {
|
| + google_update::linux_guid = switch_value.substr(0, separator);
|
| + base::linux_distro = switch_value.substr(separator + 1);
|
| + } else {
|
| + google_update::linux_guid = switch_value;
|
| + }
|
| EnableRendererCrashDumping();
|
| }
|
| }
|
|
|