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 <fcntl.h> | 5 #include <fcntl.h> |
6 #include <sys/socket.h> | 6 #include <sys/socket.h> |
7 #include <sys/uio.h> | 7 #include <sys/uio.h> |
8 #include <unistd.h> | 8 #include <unistd.h> |
9 | 9 |
10 #include <string> | 10 #include <string> |
(...skipping 18 matching lines...) Expand all Loading... |
29 // |output|. | 29 // |output|. |
30 static void write_uint64_hex(char* output, uint64_t v) { | 30 static void write_uint64_hex(char* output, uint64_t v) { |
31 static const char hextable[] = "0123456789abcdef"; | 31 static const char hextable[] = "0123456789abcdef"; |
32 | 32 |
33 for (int i = 15; i >= 0; --i) { | 33 for (int i = 15; i >= 0; --i) { |
34 output[i] = hextable[v & 15]; | 34 output[i] = hextable[v & 15]; |
35 v >>= 4; | 35 v >>= 4; |
36 } | 36 } |
37 } | 37 } |
38 | 38 |
39 pid_t UploadCrashDump(const char* filename, const char* crash_url, | 39 pid_t UploadCrashDump(const char* filename, |
40 unsigned crash_url_length) { | 40 const char* crash_url, |
| 41 unsigned crash_url_length, |
| 42 const char* guid, |
| 43 unsigned guid_length) { |
41 // WARNING: this code runs in a compromised context. It may not call into | 44 // WARNING: this code runs in a compromised context. It may not call into |
42 // libc nor allocate memory normally. | 45 // libc nor allocate memory normally. |
43 | 46 |
44 const int dumpfd = sys_open(filename, O_RDONLY, 0); | 47 const int dumpfd = sys_open(filename, O_RDONLY, 0); |
45 if (dumpfd < 0) { | 48 if (dumpfd < 0) { |
46 static const char msg[] = "Cannot upload crash dump: failed to open\n"; | 49 static const char msg[] = "Cannot upload crash dump: failed to open\n"; |
47 sys_write(2, msg, sizeof(msg)); | 50 sys_write(2, msg, sizeof(msg)); |
48 return -1; | 51 return -1; |
49 } | 52 } |
50 struct kernel_stat st; | 53 struct kernel_stat st; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 version_msg[i] = static_cast<char>(version[i]); | 124 version_msg[i] = static_cast<char>(version[i]); |
122 | 125 |
123 // The MIME block looks like this: | 126 // The MIME block looks like this: |
124 // BOUNDARY \r\n (0, 1) | 127 // BOUNDARY \r\n (0, 1) |
125 // Content-Disposition: form-data; name="prod" \r\n \r\n (2..6) | 128 // Content-Disposition: form-data; name="prod" \r\n \r\n (2..6) |
126 // Chrome_Linux \r\n (7, 8) | 129 // Chrome_Linux \r\n (7, 8) |
127 // BOUNDARY \r\n (9, 10) | 130 // BOUNDARY \r\n (9, 10) |
128 // Content-Disposition: form-data; name="ver" \r\n \r\n (11..15) | 131 // Content-Disposition: form-data; name="ver" \r\n \r\n (11..15) |
129 // 1.2.3.4 \r\n (16, 17) | 132 // 1.2.3.4 \r\n (16, 17) |
130 // BOUNDARY \r\n (18, 19) | 133 // BOUNDARY \r\n (18, 19) |
| 134 // Content-Disposition: form-data; name="guid" \r\n \r\n (20..24) |
| 135 // 1.2.3.4 \r\n (25, 26) |
| 136 // BOUNDARY \r\n (27, 28) |
131 // | 137 // |
132 // zero or more: | 138 // zero or more: |
133 // Content-Disposition: form-data; name="url-chunk-1" \r\n \r\n (0..5) | 139 // Content-Disposition: form-data; name="url-chunk-1" \r\n \r\n (0..5) |
134 // abcdef \r\n (6, 7) | 140 // abcdef \r\n (6, 7) |
135 // BOUNDARY \r\n (8, 9) | 141 // BOUNDARY \r\n (8, 9) |
136 // | 142 // |
137 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n (0,1,2) | 143 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n (0,1,2) |
138 // Content-Type: application/octet-stream \r\n \r\n (3,4,5) | 144 // Content-Type: application/octet-stream \r\n \r\n (3,4,5) |
139 // <dump contents> (6) | 145 // <dump contents> (6) |
140 // \r\n BOUNDARY -- \r\n (7,8,9,10) | 146 // \r\n BOUNDARY -- \r\n (7,8,9,10) |
141 | 147 |
142 static const char rn[] = {'\r', '\n'}; | 148 static const char rn[] = {'\r', '\n'}; |
143 static const char form_data_msg[] = "Content-Disposition: form-data; name=\""; | 149 static const char form_data_msg[] = "Content-Disposition: form-data; name=\""; |
144 static const char prod_msg[] = "prod"; | 150 static const char prod_msg[] = "prod"; |
145 static const char quote_msg[] = {'"'}; | 151 static const char quote_msg[] = {'"'}; |
146 static const char chrome_linux_msg[] = "Chrome_Linux"; | 152 static const char chrome_linux_msg[] = "Chrome_Linux"; |
147 static const char ver_msg[] = "ver"; | 153 static const char ver_msg[] = "ver"; |
| 154 static const char guid_msg[] = "guid"; |
148 static const char dashdash_msg[] = {'-', '-'}; | 155 static const char dashdash_msg[] = {'-', '-'}; |
149 static const char dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; | 156 static const char dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; |
150 static const char content_type_msg[] = | 157 static const char content_type_msg[] = |
151 "Content-Type: application/octet-stream"; | 158 "Content-Type: application/octet-stream"; |
152 static const char url_chunk_msg[] = "url-chunk-"; | 159 static const char url_chunk_msg[] = "url-chunk-"; |
153 | 160 |
154 struct kernel_iovec iov[20]; | 161 struct kernel_iovec iov[29]; |
155 iov[0].iov_base = mime_boundary; | 162 iov[0].iov_base = mime_boundary; |
156 iov[0].iov_len = sizeof(mime_boundary) - 1; | 163 iov[0].iov_len = sizeof(mime_boundary) - 1; |
157 iov[1].iov_base = const_cast<char*>(rn); | 164 iov[1].iov_base = const_cast<char*>(rn); |
158 iov[1].iov_len = sizeof(rn); | 165 iov[1].iov_len = sizeof(rn); |
159 | 166 |
160 iov[2].iov_base = const_cast<char*>(form_data_msg); | 167 iov[2].iov_base = const_cast<char*>(form_data_msg); |
161 iov[2].iov_len = sizeof(form_data_msg) - 1; | 168 iov[2].iov_len = sizeof(form_data_msg) - 1; |
162 iov[3].iov_base = const_cast<char*>(prod_msg); | 169 iov[3].iov_base = const_cast<char*>(prod_msg); |
163 iov[3].iov_len = sizeof(prod_msg) - 1; | 170 iov[3].iov_len = sizeof(prod_msg) - 1; |
164 iov[4].iov_base = const_cast<char*>(quote_msg); | 171 iov[4].iov_base = const_cast<char*>(quote_msg); |
(...skipping 27 matching lines...) Expand all Loading... |
192 iov[16].iov_base = const_cast<char*>(version_msg); | 199 iov[16].iov_base = const_cast<char*>(version_msg); |
193 iov[16].iov_len = sizeof(version_msg) - 1; | 200 iov[16].iov_len = sizeof(version_msg) - 1; |
194 iov[17].iov_base = const_cast<char*>(rn); | 201 iov[17].iov_base = const_cast<char*>(rn); |
195 iov[17].iov_len = sizeof(rn); | 202 iov[17].iov_len = sizeof(rn); |
196 | 203 |
197 iov[18].iov_base = mime_boundary; | 204 iov[18].iov_base = mime_boundary; |
198 iov[18].iov_len = sizeof(mime_boundary) - 1; | 205 iov[18].iov_len = sizeof(mime_boundary) - 1; |
199 iov[19].iov_base = const_cast<char*>(rn); | 206 iov[19].iov_base = const_cast<char*>(rn); |
200 iov[19].iov_len = sizeof(rn); | 207 iov[19].iov_len = sizeof(rn); |
201 | 208 |
202 sys_writev(fd, iov, 20); | 209 iov[20].iov_base = const_cast<char*>(form_data_msg); |
| 210 iov[20].iov_len = sizeof(form_data_msg) - 1; |
| 211 iov[21].iov_base = const_cast<char*>(guid_msg); |
| 212 iov[21].iov_len = sizeof(guid_msg) - 1; |
| 213 iov[22].iov_base = const_cast<char*>(quote_msg); |
| 214 iov[22].iov_len = sizeof(quote_msg); |
| 215 iov[23].iov_base = const_cast<char*>(rn); |
| 216 iov[23].iov_len = sizeof(rn); |
| 217 iov[24].iov_base = const_cast<char*>(rn); |
| 218 iov[24].iov_len = sizeof(rn); |
| 219 |
| 220 iov[25].iov_base = const_cast<char*>(guid); |
| 221 iov[25].iov_len = guid_length; |
| 222 iov[26].iov_base = const_cast<char*>(rn); |
| 223 iov[26].iov_len = sizeof(rn); |
| 224 |
| 225 iov[27].iov_base = mime_boundary; |
| 226 iov[27].iov_len = sizeof(mime_boundary) - 1; |
| 227 iov[28].iov_base = const_cast<char*>(rn); |
| 228 iov[28].iov_len = sizeof(rn); |
| 229 |
| 230 sys_writev(fd, iov, 29); |
203 | 231 |
204 if (crash_url_length) { | 232 if (crash_url_length) { |
205 unsigned i = 0, done = 0; | 233 unsigned i = 0, done = 0; |
206 static const unsigned kMaxCrashChunkSize = 64; | 234 static const unsigned kMaxCrashChunkSize = 64; |
207 static const unsigned kMaxUrlLength = 8 * kMaxCrashChunkSize; | 235 static const unsigned kMaxUrlLength = 8 * kMaxCrashChunkSize; |
208 if (crash_url_length > kMaxUrlLength) | 236 if (crash_url_length > kMaxUrlLength) |
209 crash_url_length = kMaxUrlLength; | 237 crash_url_length = kMaxUrlLength; |
210 | 238 |
211 while (crash_url_length) { | 239 while (crash_url_length) { |
212 char num[16]; | 240 char num[16]; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 | 359 |
332 const pid_t child = sys_fork(); | 360 const pid_t child = sys_fork(); |
333 if (child) { | 361 if (child) { |
334 sys_close(fds[1]); | 362 sys_close(fds[1]); |
335 char id_buf[17]; | 363 char id_buf[17]; |
336 const int len = HANDLE_EINTR(read(fds[0], id_buf, sizeof(id_buf) - 1)); | 364 const int len = HANDLE_EINTR(read(fds[0], id_buf, sizeof(id_buf) - 1)); |
337 if (len > 0) { | 365 if (len > 0) { |
338 id_buf[len] = 0; | 366 id_buf[len] = 0; |
339 static const char msg[] = "\nCrash dump id: "; | 367 static const char msg[] = "\nCrash dump id: "; |
340 sys_write(2, msg, sizeof(msg) - 1); | 368 sys_write(2, msg, sizeof(msg) - 1); |
341 sys_write(2, id_buf, my_strlen(buf)); | 369 sys_write(2, id_buf, my_strlen(id_buf)); |
342 sys_write(2, "\n", 1); | 370 sys_write(2, "\n", 1); |
343 } | 371 } |
344 sys_unlink(filename); | 372 sys_unlink(filename); |
345 sys_unlink(buf); | 373 sys_unlink(buf); |
346 sys__exit(0); | 374 sys__exit(0); |
347 } | 375 } |
348 | 376 |
349 sys_close(fds[0]); | 377 sys_close(fds[0]); |
350 sys_dup2(fds[1], 3); | 378 sys_dup2(fds[1], 3); |
351 static const char* const kWgetBinary = "/usr/bin/wget"; | 379 static const char* const kWgetBinary = "/usr/bin/wget"; |
(...skipping 10 matching lines...) Expand all Loading... |
362 execv("/usr/bin/wget", const_cast<char**>(args)); | 390 execv("/usr/bin/wget", const_cast<char**>(args)); |
363 static const char msg[] = "Cannot upload crash dump: cannot exec " | 391 static const char msg[] = "Cannot upload crash dump: cannot exec " |
364 "/usr/bin/wget\n"; | 392 "/usr/bin/wget\n"; |
365 sys_write(2, msg, sizeof(msg) - 1); | 393 sys_write(2, msg, sizeof(msg) - 1); |
366 sys__exit(1); | 394 sys__exit(1); |
367 } | 395 } |
368 | 396 |
369 return child; | 397 return child; |
370 } | 398 } |
371 | 399 |
| 400 // This is defined in chrome/browser/google_update_settings_linux.cc, it's the |
| 401 // static string containing the user's unique GUID. We send this in the crash |
| 402 // report. |
| 403 namespace google_update { |
| 404 extern std::string linux_guid; |
| 405 } |
| 406 |
372 static bool CrashDone(const char* dump_path, | 407 static bool CrashDone(const char* dump_path, |
373 const char* minidump_id, | 408 const char* minidump_id, |
374 void* context, | 409 void* context, |
375 bool succeeded) { | 410 bool succeeded) { |
376 // WARNING: this code runs in a compromised context. It may not call into | 411 // WARNING: this code runs in a compromised context. It may not call into |
377 // libc nor allocate memory normally. | 412 // libc nor allocate memory normally. |
378 if (!succeeded) | 413 if (!succeeded) |
379 return false; | 414 return false; |
380 | 415 |
381 google_breakpad::PageAllocator allocator; | 416 google_breakpad::PageAllocator allocator; |
382 const unsigned dump_path_len = my_strlen(dump_path); | 417 const unsigned dump_path_len = my_strlen(dump_path); |
383 const unsigned minidump_id_len = my_strlen(minidump_id); | 418 const unsigned minidump_id_len = my_strlen(minidump_id); |
384 char *const path = reinterpret_cast<char*>(allocator.Alloc( | 419 char *const path = reinterpret_cast<char*>(allocator.Alloc( |
385 dump_path_len + 1 /* '/' */ + minidump_id_len + | 420 dump_path_len + 1 /* '/' */ + minidump_id_len + |
386 4 /* ".dmp" */ + 1 /* NUL */)); | 421 4 /* ".dmp" */ + 1 /* NUL */)); |
387 memcpy(path, dump_path, dump_path_len); | 422 memcpy(path, dump_path, dump_path_len); |
388 path[dump_path_len] = '/'; | 423 path[dump_path_len] = '/'; |
389 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); | 424 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); |
390 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); | 425 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); |
391 path[dump_path_len + 1 + minidump_id_len + 4] = 0; | 426 path[dump_path_len + 1 + minidump_id_len + 4] = 0; |
392 | 427 |
393 UploadCrashDump(path, NULL, 0); | 428 UploadCrashDump(path, NULL, 0, google_update::linux_guid.data(), |
| 429 google_update::linux_guid.length()); |
394 | 430 |
395 return true; | 431 return true; |
396 } | 432 } |
397 | 433 |
398 void EnableCrashDumping() { | 434 void EnableCrashDumping() { |
399 // We leak this object. | 435 // We leak this object. |
400 | 436 |
401 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDone, NULL, | 437 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDone, NULL, |
402 true /* install handlers */); | 438 true /* install handlers */); |
403 } | 439 } |
(...skipping 14 matching lines...) Expand all Loading... |
418 | 454 |
419 // The length of the control message: | 455 // The length of the control message: |
420 static const unsigned kControlMsgSize = | 456 static const unsigned kControlMsgSize = |
421 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); | 457 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); |
422 | 458 |
423 union { | 459 union { |
424 struct kernel_msghdr msg; | 460 struct kernel_msghdr msg; |
425 struct msghdr sys_msg; | 461 struct msghdr sys_msg; |
426 }; | 462 }; |
427 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); | 463 my_memset(&msg, 0, sizeof(struct kernel_msghdr)); |
428 struct kernel_iovec iov[2]; | 464 struct kernel_iovec iov[3]; |
429 iov[0].iov_base = const_cast<void*>(crash_context); | 465 iov[0].iov_base = const_cast<void*>(crash_context); |
430 iov[0].iov_len = crash_context_size; | 466 iov[0].iov_len = crash_context_size; |
431 iov[1].iov_base = const_cast<char*>(renderer_logging::active_url.data()); | 467 iov[1].iov_base = const_cast<char*>(google_update::linux_guid.data()); |
432 iov[1].iov_len = renderer_logging::active_url.size(); | 468 iov[1].iov_len = google_update::linux_guid.size(); |
| 469 iov[2].iov_base = const_cast<char*>(renderer_logging::active_url.data()); |
| 470 iov[2].iov_len = renderer_logging::active_url.size(); |
433 | 471 |
434 msg.msg_iov = iov; | 472 msg.msg_iov = iov; |
435 msg.msg_iovlen = 2; | 473 msg.msg_iovlen = 3; |
436 char cmsg[kControlMsgSize]; | 474 char cmsg[kControlMsgSize]; |
437 memset(cmsg, 0, kControlMsgSize); | 475 memset(cmsg, 0, kControlMsgSize); |
438 msg.msg_control = cmsg; | 476 msg.msg_control = cmsg; |
439 msg.msg_controllen = sizeof(cmsg); | 477 msg.msg_controllen = sizeof(cmsg); |
440 | 478 |
441 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); | 479 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); |
442 hdr->cmsg_level = SOL_SOCKET; | 480 hdr->cmsg_level = SOL_SOCKET; |
443 hdr->cmsg_type = SCM_RIGHTS; | 481 hdr->cmsg_type = SCM_RIGHTS; |
444 hdr->cmsg_len = CMSG_LEN(sizeof(int)); | 482 hdr->cmsg_len = CMSG_LEN(sizeof(int)); |
445 *((int*) CMSG_DATA(hdr)) = fds[1]; | 483 *((int*) CMSG_DATA(hdr)) = fds[1]; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 | 517 |
480 // Determine the process type and take appropriate action. | 518 // Determine the process type and take appropriate action. |
481 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); | 519 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); |
482 const std::wstring process_type = | 520 const std::wstring process_type = |
483 parsed_command_line.GetSwitchValue(switches::kProcessType); | 521 parsed_command_line.GetSwitchValue(switches::kProcessType); |
484 if (process_type.empty()) | 522 if (process_type.empty()) |
485 EnableCrashDumping(); | 523 EnableCrashDumping(); |
486 else if (process_type == switches::kRendererProcess) | 524 else if (process_type == switches::kRendererProcess) |
487 EnableRendererCrashDumping(); | 525 EnableRendererCrashDumping(); |
488 } | 526 } |
OLD | NEW |