OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/browser/crash_handler_host_linux.h" | 5 #include "chrome/browser/crash_handler_host_linux.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
10 #include <sys/syscall.h> | 10 #include <sys/syscall.h> |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 if (crashing_pid == -1 || partner_fd == -1 || signal_fd == -1) { | 214 if (crashing_pid == -1 || partner_fd == -1 || signal_fd == -1) { |
215 LOG(ERROR) << "Death signal message didn't contain all expected control" | 215 LOG(ERROR) << "Death signal message didn't contain all expected control" |
216 << " messages"; | 216 << " messages"; |
217 if (partner_fd >= 0) | 217 if (partner_fd >= 0) |
218 HANDLE_EINTR(close(partner_fd)); | 218 HANDLE_EINTR(close(partner_fd)); |
219 if (signal_fd >= 0) | 219 if (signal_fd >= 0) |
220 HANDLE_EINTR(close(signal_fd)); | 220 HANDLE_EINTR(close(signal_fd)); |
221 return; | 221 return; |
222 } | 222 } |
223 | 223 |
224 // Kernel bug workaround (broken in 2.6.30 at least): | 224 // Kernel bug workaround (broken in 2.6.30 and 2.6.32, working in 2.6.38). |
225 // The kernel doesn't translate PIDs in SCM_CREDENTIALS across PID | 225 // The kernel doesn't translate PIDs in SCM_CREDENTIALS across PID |
226 // namespaces. Thus |crashing_pid| might be garbage from our point of view. | 226 // namespaces. Thus |crashing_pid| might be garbage from our point of view. |
227 // In the future we can remove this workaround, but we have to wait a couple | 227 // In the future we can remove this workaround, but we have to wait a couple |
228 // of years to be sure that it's worked its way out into the world. | 228 // of years to be sure that it's worked its way out into the world. |
| 229 // TODO(thestig) Remove the workaround when Ubuntu Lucid is deprecated. |
229 | 230 |
230 // The crashing process closes its copy of the signal_fd immediately after | 231 // The crashing process closes its copy of the signal_fd immediately after |
231 // calling sendmsg(). We can thus not reliably look for with with | 232 // calling sendmsg(). We can thus not reliably look for with with |
232 // FindProcessHoldingSocket(). But by necessity, it has to keep the | 233 // FindProcessHoldingSocket(). But by necessity, it has to keep the |
233 // partner_fd open until the crashdump is complete. | 234 // partner_fd open until the crashdump is complete. |
234 uint64_t inode_number; | 235 uint64_t inode_number; |
235 if (!base::FileDescriptorGetInode(&inode_number, partner_fd)) { | 236 if (!base::FileDescriptorGetInode(&inode_number, partner_fd)) { |
236 LOG(WARNING) << "Failed to get inode number for passed socket"; | 237 LOG(WARNING) << "Failed to get inode number for passed socket"; |
237 HANDLE_EINTR(close(partner_fd)); | 238 HANDLE_EINTR(close(partner_fd)); |
238 HANDLE_EINTR(close(signal_fd)); | 239 HANDLE_EINTR(close(signal_fd)); |
239 return; | 240 return; |
240 } | 241 } |
241 HANDLE_EINTR(close(partner_fd)); | 242 HANDLE_EINTR(close(partner_fd)); |
242 | 243 |
243 pid_t actual_crashing_pid = -1; | 244 pid_t actual_crashing_pid = -1; |
244 if (!base::FindProcessHoldingSocket(&actual_crashing_pid, inode_number)) { | 245 if (!base::FindProcessHoldingSocket(&actual_crashing_pid, inode_number)) { |
245 LOG(WARNING) << "Failed to find process holding other end of crash reply " | 246 LOG(WARNING) << "Failed to find process holding other end of crash reply " |
246 "socket"; | 247 "socket"; |
247 HANDLE_EINTR(close(signal_fd)); | 248 HANDLE_EINTR(close(signal_fd)); |
248 return; | 249 return; |
249 } | 250 } |
250 | 251 |
251 if (actual_crashing_pid != crashing_pid) { | 252 crashing_pid = actual_crashing_pid; |
252 crashing_pid = actual_crashing_pid; | |
253 | 253 |
254 // The crashing TID set inside the compromised context via sys_gettid() | 254 // The crashing TID set inside the compromised context via |
255 // in ExceptionHandler::HandleSignal is also wrong and needs to be | 255 // sys_gettid() in ExceptionHandler::HandleSignal might be wrong (if |
256 // translated. | 256 // the kernel supports PID namespacing) and may need to be |
257 // | 257 // translated. |
258 // We expect the crashing thread to be in sys_read(), waiting for use to | 258 // |
259 // write to |signal_fd|. Most newer kernels where we have the different pid | 259 // We expect the crashing thread to be in sys_read(), waiting for us to |
260 // namespaces also have /proc/[pid]/syscall, so we can look through | 260 // write to |signal_fd|. Most newer kernels where we have the different pid |
261 // |actual_crashing_pid|'s thread group and find the thread that's in the | 261 // namespaces also have /proc/[pid]/syscall, so we can look through |
262 // read syscall with the right arguments. | 262 // |actual_crashing_pid|'s thread group and find the thread that's in the |
| 263 // read syscall with the right arguments. |
263 | 264 |
264 std::string expected_syscall_data; | 265 std::string expected_syscall_data; |
265 // /proc/[pid]/syscall is formatted as follows: | 266 // /proc/[pid]/syscall is formatted as follows: |
266 // syscall_number arg1 ... arg6 sp pc | 267 // syscall_number arg1 ... arg6 sp pc |
267 // but we just check syscall_number through arg3. | 268 // but we just check syscall_number through arg3. |
268 base::StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ", | 269 base::StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ", |
269 SYS_read, tid_fd, tid_buf_addr); | 270 SYS_read, tid_fd, tid_buf_addr); |
270 pid_t crashing_tid = | 271 bool syscall_supported = false; |
271 base::FindThreadIDWithSyscall(crashing_pid, expected_syscall_data); | 272 pid_t crashing_tid = |
272 if (crashing_tid == -1) { | 273 base::FindThreadIDWithSyscall(crashing_pid, |
273 // We didn't find the thread we want. Maybe it didn't reach sys_read() | 274 expected_syscall_data, |
274 // yet, or the kernel doesn't support /proc/[pid]/syscall or the thread | 275 &syscall_supported); |
275 // went away. We'll just take a guess here and assume the crashing | 276 if (crashing_tid == -1 && syscall_supported) { |
276 // thread is the thread group leader. | 277 // We didn't find the thread we want. Maybe it didn't reach |
277 crashing_tid = crashing_pid; | 278 // sys_read() yet or the thread went away. We'll just take a |
278 } | 279 // guess here and assume the crashing thread is the thread group |
| 280 // leader. If procfs syscall is not supported by the kernel, then |
| 281 // we assume the kernel also does not support TID namespacing and |
| 282 // trust the TID passed by the crashing process. |
| 283 crashing_tid = crashing_pid; |
| 284 } |
279 | 285 |
280 ExceptionHandler::CrashContext* bad_context = | 286 ExceptionHandler::CrashContext* bad_context = |
281 reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context); | 287 reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context); |
282 bad_context->tid = crashing_tid; | 288 bad_context->tid = crashing_tid; |
283 } | |
284 | 289 |
285 // Sanitize the string data a bit more | 290 // Sanitize the string data a bit more |
286 guid[kGuidSize] = crash_url[kMaxActiveURLSize] = distro[kDistroSize] = 0; | 291 guid[kGuidSize] = crash_url[kMaxActiveURLSize] = distro[kDistroSize] = 0; |
287 | 292 |
288 // Freed in CrashDumpTask(); | 293 // Freed in CrashDumpTask(); |
289 BreakpadInfo* info = new BreakpadInfo; | 294 BreakpadInfo* info = new BreakpadInfo; |
290 | 295 |
291 info->process_type_length = process_type_.length(); | 296 info->process_type_length = process_type_.length(); |
292 char* process_type_str = new char[info->process_type_length + 1]; | 297 char* process_type_str = new char[info->process_type_length + 1]; |
293 process_type_.copy(process_type_str, info->process_type_length); | 298 process_type_.copy(process_type_str, info->process_type_length); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 } | 445 } |
441 | 446 |
442 void PpapiCrashHandlerHostLinux::SetProcessType() { | 447 void PpapiCrashHandlerHostLinux::SetProcessType() { |
443 process_type_ = "ppapi"; | 448 process_type_ = "ppapi"; |
444 } | 449 } |
445 | 450 |
446 // static | 451 // static |
447 PpapiCrashHandlerHostLinux* PpapiCrashHandlerHostLinux::GetInstance() { | 452 PpapiCrashHandlerHostLinux* PpapiCrashHandlerHostLinux::GetInstance() { |
448 return Singleton<PpapiCrashHandlerHostLinux>::get(); | 453 return Singleton<PpapiCrashHandlerHostLinux>::get(); |
449 } | 454 } |
OLD | NEW |