| 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 "chrome/app/breakpad_linux.h" | 5 #include "chrome/app/breakpad_linux.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <sys/socket.h> | 8 #include <sys/socket.h> |
| 9 #include <sys/uio.h> | 9 #include <sys/uio.h> |
| 10 #include <unistd.h> | 10 #include <unistd.h> |
| 11 | 11 |
| 12 #include <algorithm> | 12 #include <algorithm> |
| 13 #include <string> | 13 #include <string> |
| 14 | 14 |
| 15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 16 #include "base/eintr_wrapper.h" | 16 #include "base/eintr_wrapper.h" |
| 17 #include "base/file_version_info_linux.h" | 17 #include "base/file_version_info_linux.h" |
| 18 #include "base/global_descriptors_posix.h" | 18 #include "base/global_descriptors_posix.h" |
| 19 #include "base/linux_util.h" |
| 19 #include "base/path_service.h" | 20 #include "base/path_service.h" |
| 20 #include "base/rand_util.h" | 21 #include "base/rand_util.h" |
| 21 #include "base/string_util.h" | 22 #include "base/string_util.h" |
| 22 #include "breakpad/linux/directory_reader.h" | 23 #include "breakpad/linux/directory_reader.h" |
| 23 #include "breakpad/linux/exception_handler.h" | 24 #include "breakpad/linux/exception_handler.h" |
| 24 #include "breakpad/linux/linux_libc_support.h" | 25 #include "breakpad/linux/linux_libc_support.h" |
| 25 #include "breakpad/linux/linux_syscall_support.h" | 26 #include "breakpad/linux/linux_syscall_support.h" |
| 26 #include "breakpad/linux/memory.h" | 27 #include "breakpad/linux/memory.h" |
| 27 #include "chrome/common/chrome_switches.h" | 28 #include "chrome/common/chrome_switches.h" |
| 28 #include "chrome/common/chrome_descriptors.h" | 29 #include "chrome/common/chrome_descriptors.h" |
| 29 #include "chrome/installer/util/google_update_settings.h" | 30 #include "chrome/installer/util/google_update_settings.h" |
| 30 | 31 |
| 31 static const char kUploadURL[] = | 32 static const char kUploadURL[] = |
| 32 "https://clients2.google.com/cr/report"; | 33 "https://clients2.google.com/cr/report"; |
| 33 | 34 |
| 34 // Writes the value |v| as 16 hex characters to the memory pointed at by | 35 // Writes the value |v| as 16 hex characters to the memory pointed at by |
| 35 // |output|. | 36 // |output|. |
| 36 static void write_uint64_hex(char* output, uint64_t v) { | 37 static void write_uint64_hex(char* output, uint64_t v) { |
| 37 static const char hextable[] = "0123456789abcdef"; | 38 static const char hextable[] = "0123456789abcdef"; |
| 38 | 39 |
| 39 for (int i = 15; i >= 0; --i) { | 40 for (int i = 15; i >= 0; --i) { |
| 40 output[i] = hextable[v & 15]; | 41 output[i] = hextable[v & 15]; |
| 41 v >>= 4; | 42 v >>= 4; |
| 42 } | 43 } |
| 43 } | 44 } |
| 44 | 45 |
| 45 pid_t UploadCrashDump(const char* filename, | 46 pid_t UploadCrashDump(const BreakpadInfo& info) { |
| 46 const char* process_type, | |
| 47 unsigned process_type_length, | |
| 48 const char* crash_url, | |
| 49 unsigned crash_url_length, | |
| 50 const char* guid, | |
| 51 unsigned guid_length) { | |
| 52 // WARNING: this code runs in a compromised context. It may not call into | 47 // WARNING: this code runs in a compromised context. It may not call into |
| 53 // libc nor allocate memory normally. | 48 // libc nor allocate memory normally. |
| 54 | 49 |
| 55 const int dumpfd = sys_open(filename, O_RDONLY, 0); | 50 const int dumpfd = sys_open(info.filename, O_RDONLY, 0); |
| 56 if (dumpfd < 0) { | 51 if (dumpfd < 0) { |
| 57 static const char msg[] = "Cannot upload crash dump: failed to open\n"; | 52 static const char msg[] = "Cannot upload crash dump: failed to open\n"; |
| 58 sys_write(2, msg, sizeof(msg)); | 53 sys_write(2, msg, sizeof(msg)); |
| 59 return -1; | 54 return -1; |
| 60 } | 55 } |
| 61 struct kernel_stat st; | 56 struct kernel_stat st; |
| 62 if (sys_fstat(dumpfd, &st) != 0) { | 57 if (sys_fstat(dumpfd, &st) != 0) { |
| 63 static const char msg[] = "Cannot upload crash dump: stat failed\n"; | 58 static const char msg[] = "Cannot upload crash dump: stat failed\n"; |
| 64 sys_write(2, msg, sizeof(msg)); | 59 sys_write(2, msg, sizeof(msg)); |
| 65 sys_close(dumpfd); | 60 sys_close(dumpfd); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 // Chrome_Linux \r\n (7, 8) | 132 // Chrome_Linux \r\n (7, 8) |
| 138 // BOUNDARY \r\n (9, 10) | 133 // BOUNDARY \r\n (9, 10) |
| 139 // Content-Disposition: form-data; name="ver" \r\n \r\n (11..15) | 134 // Content-Disposition: form-data; name="ver" \r\n \r\n (11..15) |
| 140 // 1.2.3.4 \r\n (16, 17) | 135 // 1.2.3.4 \r\n (16, 17) |
| 141 // BOUNDARY \r\n (18, 19) | 136 // BOUNDARY \r\n (18, 19) |
| 142 // Content-Disposition: form-data; name="guid" \r\n \r\n (20..24) | 137 // Content-Disposition: form-data; name="guid" \r\n \r\n (20..24) |
| 143 // 1.2.3.4 \r\n (25, 26) | 138 // 1.2.3.4 \r\n (25, 26) |
| 144 // BOUNDARY \r\n (27, 28) | 139 // BOUNDARY \r\n (27, 28) |
| 145 // | 140 // |
| 146 // zero or more: | 141 // zero or more: |
| 142 // Content-Disposition: form-data; name="ptype" \r\n \r\n (0..4) |
| 143 // abcdef \r\n (5, 6) |
| 144 // BOUNDARY \r\n (7, 8) |
| 145 // |
| 146 // zero or more: |
| 147 // Content-Disposition: form-data; name="lsb-release" \r\n \r\n (0..4) |
| 148 // abcdef \r\n (5, 6) |
| 149 // BOUNDARY \r\n (7, 8) |
| 150 // |
| 151 // zero or more: |
| 147 // Content-Disposition: form-data; name="url-chunk-1" \r\n \r\n (0..5) | 152 // Content-Disposition: form-data; name="url-chunk-1" \r\n \r\n (0..5) |
| 148 // abcdef \r\n (6, 7) | 153 // abcdef \r\n (6, 7) |
| 149 // BOUNDARY \r\n (8, 9) | 154 // BOUNDARY \r\n (8, 9) |
| 150 // | 155 // |
| 151 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n (0,1,2) | 156 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n (0,1,2) |
| 152 // Content-Type: application/octet-stream \r\n \r\n (3,4,5) | 157 // Content-Type: application/octet-stream \r\n \r\n (3,4,5) |
| 153 // <dump contents> (6) | 158 // <dump contents> (6) |
| 154 // \r\n BOUNDARY -- \r\n (7,8,9,10) | 159 // \r\n BOUNDARY -- \r\n (7,8,9,10) |
| 155 | 160 |
| 156 static const char rn[] = {'\r', '\n'}; | 161 static const char rn[] = {'\r', '\n'}; |
| 157 static const char form_data_msg[] = "Content-Disposition: form-data; name=\""; | 162 static const char form_data_msg[] = "Content-Disposition: form-data; name=\""; |
| 158 static const char prod_msg[] = "prod"; | 163 static const char prod_msg[] = "prod"; |
| 159 static const char quote_msg[] = {'"'}; | 164 static const char quote_msg[] = {'"'}; |
| 160 static const char chrome_linux_msg[] = "Chrome_Linux"; | 165 static const char chrome_linux_msg[] = "Chrome_Linux"; |
| 161 static const char ver_msg[] = "ver"; | 166 static const char ver_msg[] = "ver"; |
| 162 static const char guid_msg[] = "guid"; | 167 static const char guid_msg[] = "guid"; |
| 163 static const char dashdash_msg[] = {'-', '-'}; | 168 static const char dashdash_msg[] = {'-', '-'}; |
| 164 static const char dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; | 169 static const char dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; |
| 165 static const char content_type_msg[] = | 170 static const char content_type_msg[] = |
| 166 "Content-Type: application/octet-stream"; | 171 "Content-Type: application/octet-stream"; |
| 167 static const char url_chunk_msg[] = "url-chunk-"; | 172 static const char url_chunk_msg[] = "url-chunk-"; |
| 168 static const char process_type_msg[] = "ptype"; | 173 static const char process_type_msg[] = "ptype"; |
| 174 static const char distro_msg[] = "lsb-release"; |
| 169 | 175 |
| 170 struct kernel_iovec iov[29]; | 176 struct kernel_iovec iov[29]; |
| 171 iov[0].iov_base = mime_boundary; | 177 iov[0].iov_base = mime_boundary; |
| 172 iov[0].iov_len = sizeof(mime_boundary) - 1; | 178 iov[0].iov_len = sizeof(mime_boundary) - 1; |
| 173 iov[1].iov_base = const_cast<char*>(rn); | 179 iov[1].iov_base = const_cast<char*>(rn); |
| 174 iov[1].iov_len = sizeof(rn); | 180 iov[1].iov_len = sizeof(rn); |
| 175 | 181 |
| 176 iov[2].iov_base = const_cast<char*>(form_data_msg); | 182 iov[2].iov_base = const_cast<char*>(form_data_msg); |
| 177 iov[2].iov_len = sizeof(form_data_msg) - 1; | 183 iov[2].iov_len = sizeof(form_data_msg) - 1; |
| 178 iov[3].iov_base = const_cast<char*>(prod_msg); | 184 iov[3].iov_base = const_cast<char*>(prod_msg); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 iov[20].iov_len = sizeof(form_data_msg) - 1; | 225 iov[20].iov_len = sizeof(form_data_msg) - 1; |
| 220 iov[21].iov_base = const_cast<char*>(guid_msg); | 226 iov[21].iov_base = const_cast<char*>(guid_msg); |
| 221 iov[21].iov_len = sizeof(guid_msg) - 1; | 227 iov[21].iov_len = sizeof(guid_msg) - 1; |
| 222 iov[22].iov_base = const_cast<char*>(quote_msg); | 228 iov[22].iov_base = const_cast<char*>(quote_msg); |
| 223 iov[22].iov_len = sizeof(quote_msg); | 229 iov[22].iov_len = sizeof(quote_msg); |
| 224 iov[23].iov_base = const_cast<char*>(rn); | 230 iov[23].iov_base = const_cast<char*>(rn); |
| 225 iov[23].iov_len = sizeof(rn); | 231 iov[23].iov_len = sizeof(rn); |
| 226 iov[24].iov_base = const_cast<char*>(rn); | 232 iov[24].iov_base = const_cast<char*>(rn); |
| 227 iov[24].iov_len = sizeof(rn); | 233 iov[24].iov_len = sizeof(rn); |
| 228 | 234 |
| 229 iov[25].iov_base = const_cast<char*>(guid); | 235 iov[25].iov_base = const_cast<char*>(info.guid); |
| 230 iov[25].iov_len = guid_length; | 236 iov[25].iov_len = info.guid_length; |
| 231 iov[26].iov_base = const_cast<char*>(rn); | 237 iov[26].iov_base = const_cast<char*>(rn); |
| 232 iov[26].iov_len = sizeof(rn); | 238 iov[26].iov_len = sizeof(rn); |
| 233 | 239 |
| 234 iov[27].iov_base = mime_boundary; | 240 iov[27].iov_base = mime_boundary; |
| 235 iov[27].iov_len = sizeof(mime_boundary) - 1; | 241 iov[27].iov_len = sizeof(mime_boundary) - 1; |
| 236 iov[28].iov_base = const_cast<char*>(rn); | 242 iov[28].iov_base = const_cast<char*>(rn); |
| 237 iov[28].iov_len = sizeof(rn); | 243 iov[28].iov_len = sizeof(rn); |
| 238 | 244 |
| 239 sys_writev(fd, iov, 29); | 245 sys_writev(fd, iov, 29); |
| 240 | 246 |
| 241 if (process_type_length) { | 247 if (info.process_type_length) { |
| 242 iov[0].iov_base = const_cast<char*>(form_data_msg); | 248 iov[0].iov_base = const_cast<char*>(form_data_msg); |
| 243 iov[0].iov_len = sizeof(form_data_msg) - 1; | 249 iov[0].iov_len = sizeof(form_data_msg) - 1; |
| 244 iov[1].iov_base = const_cast<char*>(process_type_msg); | 250 iov[1].iov_base = const_cast<char*>(process_type_msg); |
| 245 iov[1].iov_len = sizeof(process_type_msg) - 1; | 251 iov[1].iov_len = sizeof(process_type_msg) - 1; |
| 246 iov[2].iov_base = const_cast<char*>(quote_msg); | 252 iov[2].iov_base = const_cast<char*>(quote_msg); |
| 247 iov[2].iov_len = sizeof(quote_msg); | 253 iov[2].iov_len = sizeof(quote_msg); |
| 248 iov[3].iov_base = const_cast<char*>(rn); | 254 iov[3].iov_base = const_cast<char*>(rn); |
| 249 iov[3].iov_len = sizeof(rn); | 255 iov[3].iov_len = sizeof(rn); |
| 250 iov[4].iov_base = const_cast<char*>(rn); | 256 iov[4].iov_base = const_cast<char*>(rn); |
| 251 iov[4].iov_len = sizeof(rn); | 257 iov[4].iov_len = sizeof(rn); |
| 252 | 258 |
| 253 iov[5].iov_base = const_cast<char*>(process_type); | 259 iov[5].iov_base = const_cast<char*>(info.process_type); |
| 254 iov[5].iov_len = process_type_length; | 260 iov[5].iov_len = info.process_type_length; |
| 255 iov[6].iov_base = const_cast<char*>(rn); | 261 iov[6].iov_base = const_cast<char*>(rn); |
| 256 iov[6].iov_len = sizeof(rn); | 262 iov[6].iov_len = sizeof(rn); |
| 257 iov[7].iov_base = mime_boundary; | 263 iov[7].iov_base = mime_boundary; |
| 258 iov[7].iov_len = sizeof(mime_boundary) - 1; | 264 iov[7].iov_len = sizeof(mime_boundary) - 1; |
| 259 iov[8].iov_base = const_cast<char*>(rn); | 265 iov[8].iov_base = const_cast<char*>(rn); |
| 260 iov[8].iov_len = sizeof(rn); | 266 iov[8].iov_len = sizeof(rn); |
| 261 | 267 |
| 262 sys_writev(fd, iov, 9); | 268 sys_writev(fd, iov, 9); |
| 263 } | 269 } |
| 264 | 270 |
| 265 if (crash_url_length) { | 271 if (info.distro_length) { |
| 266 unsigned i = 0, done = 0; | 272 iov[0].iov_base = const_cast<char*>(form_data_msg); |
| 273 iov[0].iov_len = sizeof(form_data_msg) - 1; |
| 274 iov[1].iov_base = const_cast<char*>(distro_msg); |
| 275 iov[1].iov_len = sizeof(distro_msg) - 1; |
| 276 iov[2].iov_base = const_cast<char*>(quote_msg); |
| 277 iov[2].iov_len = sizeof(quote_msg); |
| 278 iov[3].iov_base = const_cast<char*>(rn); |
| 279 iov[3].iov_len = sizeof(rn); |
| 280 iov[4].iov_base = const_cast<char*>(rn); |
| 281 iov[4].iov_len = sizeof(rn); |
| 282 |
| 283 iov[5].iov_base = const_cast<char*>(info.distro); |
| 284 iov[5].iov_len = info.distro_length; |
| 285 iov[6].iov_base = const_cast<char*>(rn); |
| 286 iov[6].iov_len = sizeof(rn); |
| 287 iov[7].iov_base = mime_boundary; |
| 288 iov[7].iov_len = sizeof(mime_boundary) - 1; |
| 289 iov[8].iov_base = const_cast<char*>(rn); |
| 290 iov[8].iov_len = sizeof(rn); |
| 291 |
| 292 sys_writev(fd, iov, 9); |
| 293 } |
| 294 |
| 295 if (info.crash_url_length) { |
| 296 unsigned i = 0, done = 0, crash_url_length = info.crash_url_length; |
| 267 static const unsigned kMaxCrashChunkSize = 64; | 297 static const unsigned kMaxCrashChunkSize = 64; |
| 268 static const unsigned kMaxUrlLength = 8 * kMaxCrashChunkSize; | 298 static const unsigned kMaxUrlLength = 8 * kMaxCrashChunkSize; |
| 269 if (crash_url_length > kMaxUrlLength) | 299 if (crash_url_length > kMaxUrlLength) |
| 270 crash_url_length = kMaxUrlLength; | 300 crash_url_length = kMaxUrlLength; |
| 271 | 301 |
| 272 while (crash_url_length) { | 302 while (crash_url_length) { |
| 273 char num[16]; | 303 char num[16]; |
| 274 const unsigned num_len = my_int_len(++i); | 304 const unsigned num_len = my_int_len(++i); |
| 275 my_itos(num, i, num_len); | 305 my_itos(num, i, num_len); |
| 276 | 306 |
| 277 iov[0].iov_base = const_cast<char*>(form_data_msg); | 307 iov[0].iov_base = const_cast<char*>(form_data_msg); |
| 278 iov[0].iov_len = sizeof(form_data_msg) - 1; | 308 iov[0].iov_len = sizeof(form_data_msg) - 1; |
| 279 iov[1].iov_base = const_cast<char*>(url_chunk_msg); | 309 iov[1].iov_base = const_cast<char*>(url_chunk_msg); |
| 280 iov[1].iov_len = sizeof(url_chunk_msg) - 1; | 310 iov[1].iov_len = sizeof(url_chunk_msg) - 1; |
| 281 iov[2].iov_base = num; | 311 iov[2].iov_base = num; |
| 282 iov[2].iov_len = num_len; | 312 iov[2].iov_len = num_len; |
| 283 iov[3].iov_base = const_cast<char*>(quote_msg); | 313 iov[3].iov_base = const_cast<char*>(quote_msg); |
| 284 iov[3].iov_len = sizeof(quote_msg); | 314 iov[3].iov_len = sizeof(quote_msg); |
| 285 iov[4].iov_base = const_cast<char*>(rn); | 315 iov[4].iov_base = const_cast<char*>(rn); |
| 286 iov[4].iov_len = sizeof(rn); | 316 iov[4].iov_len = sizeof(rn); |
| 287 iov[5].iov_base = const_cast<char*>(rn); | 317 iov[5].iov_base = const_cast<char*>(rn); |
| 288 iov[5].iov_len = sizeof(rn); | 318 iov[5].iov_len = sizeof(rn); |
| 289 | 319 |
| 290 const unsigned len = crash_url_length > kMaxCrashChunkSize ? | 320 const unsigned len = crash_url_length > kMaxCrashChunkSize ? |
| 291 kMaxCrashChunkSize : crash_url_length; | 321 kMaxCrashChunkSize : crash_url_length; |
| 292 iov[6].iov_base = const_cast<char*>(crash_url + done); | 322 iov[6].iov_base = const_cast<char*>(info.crash_url + done); |
| 293 iov[6].iov_len = len; | 323 iov[6].iov_len = len; |
| 294 iov[7].iov_base = const_cast<char*>(rn); | 324 iov[7].iov_base = const_cast<char*>(rn); |
| 295 iov[7].iov_len = sizeof(rn); | 325 iov[7].iov_len = sizeof(rn); |
| 296 iov[8].iov_base = mime_boundary; | 326 iov[8].iov_base = mime_boundary; |
| 297 iov[8].iov_len = sizeof(mime_boundary) - 1; | 327 iov[8].iov_len = sizeof(mime_boundary) - 1; |
| 298 iov[9].iov_base = const_cast<char*>(rn); | 328 iov[9].iov_base = const_cast<char*>(rn); |
| 299 iov[9].iov_len = sizeof(rn); | 329 iov[9].iov_len = sizeof(rn); |
| 300 | 330 |
| 301 sys_writev(fd, iov, 10); | 331 sys_writev(fd, iov, 10); |
| 302 | 332 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 sys_close(fds[1]); | 425 sys_close(fds[1]); |
| 396 char id_buf[17]; | 426 char id_buf[17]; |
| 397 const int len = HANDLE_EINTR(read(fds[0], id_buf, sizeof(id_buf) - 1)); | 427 const int len = HANDLE_EINTR(read(fds[0], id_buf, sizeof(id_buf) - 1)); |
| 398 if (len > 0) { | 428 if (len > 0) { |
| 399 id_buf[len] = 0; | 429 id_buf[len] = 0; |
| 400 static const char msg[] = "\nCrash dump id: "; | 430 static const char msg[] = "\nCrash dump id: "; |
| 401 sys_write(2, msg, sizeof(msg) - 1); | 431 sys_write(2, msg, sizeof(msg) - 1); |
| 402 sys_write(2, id_buf, my_strlen(id_buf)); | 432 sys_write(2, id_buf, my_strlen(id_buf)); |
| 403 sys_write(2, "\n", 1); | 433 sys_write(2, "\n", 1); |
| 404 } | 434 } |
| 405 sys_unlink(filename); | 435 sys_unlink(info.filename); |
| 406 sys_unlink(buf); | 436 sys_unlink(buf); |
| 407 sys__exit(0); | 437 sys__exit(0); |
| 408 } | 438 } |
| 409 | 439 |
| 410 sys_close(fds[0]); | 440 sys_close(fds[0]); |
| 411 sys_dup2(fds[1], 3); | 441 sys_dup2(fds[1], 3); |
| 412 static const char* const kWgetBinary = "/usr/bin/wget"; | 442 static const char* const kWgetBinary = "/usr/bin/wget"; |
| 413 const char* args[] = { | 443 const char* args[] = { |
| 414 kWgetBinary, | 444 kWgetBinary, |
| 415 header, | 445 header, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 430 return child; | 460 return child; |
| 431 } | 461 } |
| 432 | 462 |
| 433 // This is defined in chrome/browser/google_update_settings_linux.cc, it's the | 463 // This is defined in chrome/browser/google_update_settings_linux.cc, it's the |
| 434 // static string containing the user's unique GUID. We send this in the crash | 464 // static string containing the user's unique GUID. We send this in the crash |
| 435 // report. | 465 // report. |
| 436 namespace google_update { | 466 namespace google_update { |
| 437 extern std::string linux_guid; | 467 extern std::string linux_guid; |
| 438 } | 468 } |
| 439 | 469 |
| 470 // This is defined in base/linux_util.cc, it's the static string containing the |
| 471 // user's distro info. We send this in the crash report. |
| 472 namespace base { |
| 473 extern std::string linux_distro; |
| 474 } |
| 475 |
| 440 static bool CrashDone(const char* dump_path, | 476 static bool CrashDone(const char* dump_path, |
| 441 const char* minidump_id, | 477 const char* minidump_id, |
| 442 void* context, | 478 void* context, |
| 443 bool succeeded) { | 479 bool succeeded) { |
| 444 // WARNING: this code runs in a compromised context. It may not call into | 480 // WARNING: this code runs in a compromised context. It may not call into |
| 445 // libc nor allocate memory normally. | 481 // libc nor allocate memory normally. |
| 446 if (!succeeded) | 482 if (!succeeded) |
| 447 return false; | 483 return false; |
| 448 | 484 |
| 449 google_breakpad::PageAllocator allocator; | 485 google_breakpad::PageAllocator allocator; |
| 450 const unsigned dump_path_len = my_strlen(dump_path); | 486 const unsigned dump_path_len = my_strlen(dump_path); |
| 451 const unsigned minidump_id_len = my_strlen(minidump_id); | 487 const unsigned minidump_id_len = my_strlen(minidump_id); |
| 452 char *const path = reinterpret_cast<char*>(allocator.Alloc( | 488 char *const path = reinterpret_cast<char*>(allocator.Alloc( |
| 453 dump_path_len + 1 /* '/' */ + minidump_id_len + | 489 dump_path_len + 1 /* '/' */ + minidump_id_len + |
| 454 4 /* ".dmp" */ + 1 /* NUL */)); | 490 4 /* ".dmp" */ + 1 /* NUL */)); |
| 455 memcpy(path, dump_path, dump_path_len); | 491 memcpy(path, dump_path, dump_path_len); |
| 456 path[dump_path_len] = '/'; | 492 path[dump_path_len] = '/'; |
| 457 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); | 493 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); |
| 458 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); | 494 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); |
| 459 path[dump_path_len + 1 + minidump_id_len + 4] = 0; | 495 path[dump_path_len + 1 + minidump_id_len + 4] = 0; |
| 460 | 496 |
| 461 UploadCrashDump(path, "browser", 7, NULL, 0, google_update::linux_guid.data(), | 497 BreakpadInfo info; |
| 462 google_update::linux_guid.length()); | 498 info.filename = path; |
| 499 info.process_type = "browser"; |
| 500 info.process_type_length = 7; |
| 501 info.crash_url = NULL; |
| 502 info.crash_url_length = 0; |
| 503 info.guid = google_update::linux_guid.data(); |
| 504 info.guid_length = google_update::linux_guid.length(); |
| 505 info.distro = base::linux_distro.data(); |
| 506 info.distro_length = base::linux_distro.length(); |
| 507 UploadCrashDump(info); |
| 463 | 508 |
| 464 return true; | 509 return true; |
| 465 } | 510 } |
| 466 | 511 |
| 467 void EnableCrashDumping() { | 512 void EnableCrashDumping() { |
| 468 // We leak this object. | 513 // We leak this object. |
| 469 | 514 |
| 470 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDone, NULL, | 515 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDone, NULL, |
| 471 true /* install handlers */); | 516 true /* install handlers */); |
| 472 } | 517 } |
| 473 | 518 |
| 474 // This is defined in chrome/common/child_process_logging_linux.cc, it's the | 519 // This is defined in chrome/common/child_process_logging_linux.cc, it's the |
| 475 // static string containing the current active URL. We send this in the crash | 520 // static string containing the current active URL. We send this in the crash |
| 476 // report. | 521 // report. |
| 477 namespace child_process_logging { | 522 namespace child_process_logging { |
| 478 extern std::string active_url; | 523 extern std::string active_url; |
| 479 } | 524 } |
| 480 | 525 |
| 481 static bool | 526 static bool |
| 482 RendererCrashHandler(const void* crash_context, size_t crash_context_size, | 527 RendererCrashHandler(const void* crash_context, size_t crash_context_size, |
| 483 void* context) { | 528 void* context) { |
| 484 const int fd = (int) context; | 529 const int fd = reinterpret_cast<int>(context); |
| 485 int fds[2]; | 530 int fds[2]; |
| 486 socketpair(AF_UNIX, SOCK_STREAM, 0, fds); | 531 socketpair(AF_UNIX, SOCK_STREAM, 0, fds); |
| 487 char guid[kGuidSize] = {0}; | 532 char guid[kGuidSize] = {0}; |
| 488 char crash_url[kMaxActiveURLSize + 1] = {0}; | 533 char crash_url[kMaxActiveURLSize + 1] = {0}; |
| 534 char distro[kDistroSize + 1] = {0}; |
| 489 const unsigned guid_len = std::min(google_update::linux_guid.size(), | 535 const unsigned guid_len = std::min(google_update::linux_guid.size(), |
| 490 kGuidSize); | 536 kGuidSize); |
| 491 const unsigned crash_url_len = | 537 const unsigned crash_url_len = |
| 492 std::min(child_process_logging::active_url.size(), kMaxActiveURLSize); | 538 std::min(child_process_logging::active_url.size(), kMaxActiveURLSize); |
| 539 const unsigned distro_len = |
| 540 std::min(base::linux_distro.size(), kDistroSize); |
| 493 memcpy(guid, google_update::linux_guid.data(), guid_len); | 541 memcpy(guid, google_update::linux_guid.data(), guid_len); |
| 494 memcpy(crash_url, child_process_logging::active_url.data(), crash_url_len); | 542 memcpy(crash_url, child_process_logging::active_url.data(), crash_url_len); |
| 543 memcpy(distro, base::linux_distro.data(), distro_len); |
| 495 | 544 |
| 496 // The length of the control message: | 545 // The length of the control message: |
| 497 static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int)); | 546 static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int)); |
| 498 | 547 |
| 499 struct kernel_msghdr msg; | 548 struct kernel_msghdr msg; |
| 500 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); | 549 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
| 501 struct kernel_iovec iov[3]; | 550 struct kernel_iovec iov[4]; |
| 502 iov[0].iov_base = const_cast<void*>(crash_context); | 551 iov[0].iov_base = const_cast<void*>(crash_context); |
| 503 iov[0].iov_len = crash_context_size; | 552 iov[0].iov_len = crash_context_size; |
| 504 iov[1].iov_base = guid; | 553 iov[1].iov_base = guid; |
| 505 iov[1].iov_len = kGuidSize + 1; | 554 iov[1].iov_len = kGuidSize + 1; |
| 506 iov[2].iov_base = crash_url; | 555 iov[2].iov_base = crash_url; |
| 507 iov[2].iov_len = kMaxActiveURLSize + 1; | 556 iov[2].iov_len = kMaxActiveURLSize + 1; |
| 557 iov[3].iov_base = distro; |
| 558 iov[3].iov_len = kDistroSize + 1; |
| 508 | 559 |
| 509 msg.msg_iov = iov; | 560 msg.msg_iov = iov; |
| 510 msg.msg_iovlen = 3; | 561 msg.msg_iovlen = 4; |
| 511 char cmsg[kControlMsgSize]; | 562 char cmsg[kControlMsgSize]; |
| 512 memset(cmsg, 0, kControlMsgSize); | 563 memset(cmsg, 0, kControlMsgSize); |
| 513 msg.msg_control = cmsg; | 564 msg.msg_control = cmsg; |
| 514 msg.msg_controllen = sizeof(cmsg); | 565 msg.msg_controllen = sizeof(cmsg); |
| 515 | 566 |
| 516 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); | 567 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); |
| 517 hdr->cmsg_level = SOL_SOCKET; | 568 hdr->cmsg_level = SOL_SOCKET; |
| 518 hdr->cmsg_type = SCM_RIGHTS; | 569 hdr->cmsg_type = SCM_RIGHTS; |
| 519 hdr->cmsg_len = CMSG_LEN(sizeof(int)); | 570 hdr->cmsg_len = CMSG_LEN(sizeof(int)); |
| 520 *((int*) CMSG_DATA(hdr)) = fds[1]; | 571 *((int*) CMSG_DATA(hdr)) = fds[1]; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 538 } | 589 } |
| 539 | 590 |
| 540 void InitCrashReporter() { | 591 void InitCrashReporter() { |
| 541 // Determine the process type and take appropriate action. | 592 // Determine the process type and take appropriate action. |
| 542 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); | 593 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); |
| 543 const std::wstring process_type = | 594 const std::wstring process_type = |
| 544 parsed_command_line.GetSwitchValue(switches::kProcessType); | 595 parsed_command_line.GetSwitchValue(switches::kProcessType); |
| 545 if (process_type.empty()) { | 596 if (process_type.empty()) { |
| 546 if (!GoogleUpdateSettings::GetCollectStatsConsent()) | 597 if (!GoogleUpdateSettings::GetCollectStatsConsent()) |
| 547 return; | 598 return; |
| 599 base::GetLinuxDistro(); // Initialize base::linux_distro if needed. |
| 548 EnableCrashDumping(); | 600 EnableCrashDumping(); |
| 549 } else if (process_type == switches::kRendererProcess || | 601 } else if (process_type == switches::kRendererProcess || |
| 550 process_type == switches::kZygoteProcess) { | 602 process_type == switches::kZygoteProcess) { |
| 551 // We might be chrooted in a zygote or renderer process so we cannot call | 603 // We might be chrooted in a zygote or renderer process so we cannot call |
| 552 // GetCollectStatsConsent because that needs access the the user's home | 604 // GetCollectStatsConsent because that needs access the the user's home |
| 553 // dir. Instead, we set a command line flag for these processes. | 605 // dir. Instead, we set a command line flag for these processes. |
| 554 if (!parsed_command_line.HasSwitch(switches::kRendererCrashDump)) | 606 if (!parsed_command_line.HasSwitch(switches::kRendererCrashDump)) |
| 555 return; | 607 return; |
| 556 google_update::linux_guid = WideToASCII( | 608 // Get the guid and linux distro from the command line switch. |
| 609 std::string switch_value = WideToASCII( |
| 557 parsed_command_line.GetSwitchValue(switches::kRendererCrashDump)); | 610 parsed_command_line.GetSwitchValue(switches::kRendererCrashDump)); |
| 611 size_t separator = switch_value.find(","); |
| 612 if (separator != std::string::npos) { |
| 613 google_update::linux_guid = switch_value.substr(0, separator); |
| 614 base::linux_distro = switch_value.substr(separator + 1); |
| 615 } else { |
| 616 google_update::linux_guid = switch_value; |
| 617 } |
| 558 EnableRendererCrashDumping(); | 618 EnableRendererCrashDumping(); |
| 559 } | 619 } |
| 560 } | 620 } |
| OLD | NEW |