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 |