| Index: chrome/app/breakpad_linux.cc
|
| ===================================================================
|
| --- chrome/app/breakpad_linux.cc (revision 152746)
|
| +++ chrome/app/breakpad_linux.cc (working copy)
|
| @@ -10,6 +10,7 @@
|
|
|
| #include <fcntl.h>
|
| #include <poll.h>
|
| +#include <signal.h>
|
| #include <stdlib.h>
|
| #include <sys/socket.h>
|
| #include <sys/time.h>
|
| @@ -54,6 +55,10 @@
|
| #include "sandbox/linux/seccomp-legacy/linux_syscall_support.h"
|
| #endif
|
|
|
| +#if defined(ADDRESS_SANITIZER)
|
| +#include <ucontext.h> // for getcontext().
|
| +#endif
|
| +
|
| #if defined(OS_ANDROID)
|
| #define STAT_STRUCT struct stat
|
| #define FSTAT_FUNC fstat
|
| @@ -73,12 +78,21 @@
|
|
|
| namespace {
|
|
|
| +#if !defined(ADDRESS_SANITIZER)
|
| const char kUploadURL[] = "https://clients2.google.com/cr/report";
|
| +#else
|
| +// AddressSanitizer should currently upload the crash reports to the staging
|
| +// crash server.
|
| +const char kUploadURL[] = "https://clients2.google.com/cr/staging_report";
|
| +#endif
|
|
|
| bool g_is_crash_reporter_enabled = false;
|
| uint64_t g_process_start_time = 0;
|
| char* g_crash_log_path = NULL;
|
| ExceptionHandler* g_breakpad = NULL;
|
| +#if defined(ADDRESS_SANITIZER)
|
| +const char* g_asan_report_str = NULL;
|
| +#endif
|
|
|
| // Writes the value |v| as 16 hex characters to the memory pointed at by
|
| // |output|.
|
| @@ -171,6 +185,9 @@
|
| const char g_quote_msg[] = "\"";
|
| const char g_dashdash_msg[] = "--";
|
| const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\"";
|
| +#if defined(ADDRESS_SANITIZER)
|
| +const char g_log_msg[] = "upload_file_log\"; filename=\"log\"";
|
| +#endif
|
| const char g_content_type_msg[] = "Content-Type: application/octet-stream";
|
|
|
| // MimeWriter manages an iovec for writing MIMEs to a file.
|
| @@ -210,10 +227,10 @@
|
| size_t chunk_size,
|
| bool strip_trailing_spaces);
|
|
|
| - // Add binary file dump. Currently this is only done once, so the name is
|
| - // fixed.
|
| - void AddFileDump(uint8_t* file_data,
|
| - size_t file_size);
|
| + // Add binary file contents to be uploaded with the specified filename.
|
| + void AddFileContents(const char* filename_msg,
|
| + uint8_t* file_data,
|
| + size_t file_size);
|
|
|
| // Flush any pending iovecs to the output file.
|
| void Flush() {
|
| @@ -312,10 +329,10 @@
|
| }
|
| }
|
|
|
| -void MimeWriter::AddFileDump(uint8_t* file_data,
|
| - size_t file_size) {
|
| +void MimeWriter::AddFileContents(const char* filename_msg, uint8_t* file_data,
|
| + size_t file_size) {
|
| AddString(g_form_data_msg);
|
| - AddString(g_dump_msg);
|
| + AddString(filename_msg);
|
| AddString(g_rn);
|
| AddString(g_content_type_msg);
|
| AddString(g_rn);
|
| @@ -372,6 +389,15 @@
|
|
|
| BreakpadInfo info;
|
| info.filename = minidump.path();
|
| +#if defined(ADDRESS_SANITIZER)
|
| + google_breakpad::PageAllocator allocator;
|
| + const size_t log_path_len = my_strlen(minidump.path());
|
| + char* log_path = reinterpret_cast<char*>(allocator.Alloc(log_path_len + 1));
|
| + my_memcpy(log_path, minidump.path(), log_path_len);
|
| + my_memcpy(log_path + log_path_len - 4, ".log", 4);
|
| + log_path[log_path_len] = '\0';
|
| + info.log_filename = log_path;
|
| +#endif
|
| info.process_type = "browser";
|
| info.process_type_length = 7;
|
| info.crash_url = NULL;
|
| @@ -404,6 +430,18 @@
|
| }
|
| #endif
|
|
|
| +#if defined(ADDRESS_SANITIZER)
|
| +extern "C"
|
| +void __asan_set_error_report_callback(void (*cb)(const char*));
|
| +
|
| +extern "C"
|
| +void AsanLinuxBreakpadCallback(const char* report) {
|
| + g_asan_report_str = report;
|
| + // Send minidump here.
|
| + g_breakpad->SimulateSignalDelivery(SIGKILL);
|
| +}
|
| +#endif
|
| +
|
| void EnableCrashDumping(bool unattended) {
|
| g_is_crash_reporter_enabled = true;
|
|
|
| @@ -483,7 +521,12 @@
|
| static const unsigned kControlMsgSpaceSize = CMSG_SPACE(kControlMsgSize);
|
| static const unsigned kControlMsgLenSize = CMSG_LEN(kControlMsgSize);
|
|
|
| +#if !defined(ADDRESS_SANITIZER)
|
| const size_t kIovSize = 8;
|
| +#else
|
| + // Additional field to pass the AddressSanitizer log to the crash handler.
|
| + const size_t kIovSize = 9;
|
| +#endif
|
| struct kernel_msghdr msg;
|
| my_memset(&msg, 0, sizeof(struct kernel_msghdr));
|
| struct kernel_iovec iov[kIovSize];
|
| @@ -503,6 +546,10 @@
|
| iov[6].iov_len = sizeof(g_process_start_time);
|
| iov[7].iov_base = &base::g_oom_size;
|
| iov[7].iov_len = sizeof(base::g_oom_size);
|
| +#if defined(ADDRESS_SANITIZER)
|
| + iov[8].iov_base = const_cast<char*>(g_asan_report_str);
|
| + iov[8].iov_len = kMaxAsanReportSize + 1;
|
| +#endif
|
|
|
| msg.msg_iov = iov;
|
| msg.msg_iovlen = kIovSize;
|
| @@ -551,40 +598,59 @@
|
|
|
| } // namespace
|
|
|
| -void HandleCrashDump(const BreakpadInfo& info) {
|
| +void LoadDataFromFile(google_breakpad::PageAllocator& allocator,
|
| + const BreakpadInfo& info, const char* filename,
|
| + int* fd, uint8_t** file_data, size_t* size) {
|
| // WARNING: this code runs in a compromised context. It may not call into
|
| // libc nor allocate memory normally.
|
| + *fd = sys_open(filename, O_RDONLY, 0);
|
| + *size = 0;
|
|
|
| - const int dumpfd = sys_open(info.filename, O_RDONLY, 0);
|
| - if (dumpfd < 0) {
|
| + if (*fd < 0) {
|
| static const char msg[] = "Cannot upload crash dump: failed to open\n";
|
| WriteLog(msg, sizeof(msg));
|
| return;
|
| }
|
| STAT_STRUCT st;
|
| - if (FSTAT_FUNC(dumpfd, &st) != 0) {
|
| + if (FSTAT_FUNC(*fd, &st) != 0) {
|
| static const char msg[] = "Cannot upload crash dump: stat failed\n";
|
| WriteLog(msg, sizeof(msg));
|
| - IGNORE_RET(sys_close(dumpfd));
|
| + IGNORE_RET(sys_close(*fd));
|
| return;
|
| }
|
|
|
| - google_breakpad::PageAllocator allocator;
|
| -
|
| - uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
|
| - if (!dump_data) {
|
| + *file_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
|
| + if (!(*file_data)) {
|
| static const char msg[] = "Cannot upload crash dump: cannot alloc\n";
|
| WriteLog(msg, sizeof(msg));
|
| - IGNORE_RET(sys_close(dumpfd));
|
| + IGNORE_RET(sys_close(*fd));
|
| return;
|
| }
|
| + my_memset(*file_data, 0xf, st.st_size);
|
|
|
| - sys_read(dumpfd, dump_data, st.st_size);
|
| - IGNORE_RET(sys_close(dumpfd));
|
| + *size = st.st_size;
|
| + sys_read(*fd, *file_data, *size);
|
| + IGNORE_RET(sys_close(*fd));
|
| +}
|
|
|
| +void HandleCrashDump(const BreakpadInfo& info) {
|
| + int dumpfd;
|
| + size_t dump_size;
|
| + uint8_t *dump_data;
|
| + google_breakpad::PageAllocator allocator;
|
| + LoadDataFromFile(allocator, info, info.filename,
|
| + &dumpfd, &dump_data, &dump_size);
|
| +#if defined(ADDRESS_SANITIZER)
|
| + int logfd;
|
| + size_t log_size;
|
| + uint8_t *log_data;
|
| + // Load the AddressSanitizer log into log_data.
|
| + LoadDataFromFile(allocator, info, info.log_filename,
|
| + &logfd, &log_data, &log_size);
|
| +#endif
|
| +
|
| // We need to build a MIME block for uploading to the server. Since we are
|
| // going to fork and run wget, it needs to be written to a temp file.
|
| -
|
| const int ufd = sys_open("/dev/urandom", O_RDONLY, 0);
|
| if (ufd < 0) {
|
| static const char msg[] = "Cannot upload crash dump because /dev/urandom"
|
| @@ -916,7 +982,12 @@
|
| writer.Flush();
|
| }
|
|
|
| - writer.AddFileDump(dump_data, st.st_size);
|
| + writer.AddFileContents(g_dump_msg, dump_data, dump_size);
|
| +#if defined(ADDRESS_SANITIZER)
|
| + // Append a multipart boundary and the contents of the AddressSanitizer log.
|
| + writer.AddBoundary();
|
| + writer.AddFileContents(g_log_msg, log_data, log_size);
|
| +#endif
|
| writer.AddEnd();
|
| writer.Flush();
|
|
|
| @@ -1097,6 +1168,9 @@
|
|
|
| // Helper process.
|
| IGNORE_RET(sys_unlink(info.filename));
|
| +#if defined(ADDRESS_SANITIZER)
|
| + IGNORE_RET(sys_unlink(info.log_filename));
|
| +#endif
|
| IGNORE_RET(sys_unlink(temp_file));
|
| sys__exit(0);
|
| }
|
| @@ -1158,6 +1232,10 @@
|
| g_process_start_time = 0;
|
|
|
| logging::SetDumpWithoutCrashingFunction(&DumpProcess);
|
| +#if defined(ADDRESS_SANITIZER)
|
| + // Register the callback for AddressSanitizer error reporting.
|
| + __asan_set_error_report_callback(AsanLinuxBreakpadCallback);
|
| +#endif
|
| }
|
|
|
| bool IsCrashReporterEnabled() {
|
|
|