Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(549)

Side by Side Diff: chrome/browser/crash_handler_host_linux.cc

Issue 2961008: Linux: Guess the thread id for crashing renderers in a different PID namespac... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« base/linux_util.cc ('K') | « chrome/app/breakpad_linux.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/types.h> 11 #include <sys/types.h>
11 #include <unistd.h> 12 #include <unistd.h>
12 13
13 #include "base/eintr_wrapper.h" 14 #include "base/eintr_wrapper.h"
14 #include "base/file_path.h" 15 #include "base/file_path.h"
15 #include "base/format_macros.h" 16 #include "base/format_macros.h"
16 #include "base/linux_util.h" 17 #include "base/linux_util.h"
17 #include "base/logging.h" 18 #include "base/logging.h"
18 #include "base/message_loop.h" 19 #include "base/message_loop.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/src/client/linux/handler/exception_handler.h" 23 #include "breakpad/src/client/linux/handler/exception_handler.h"
23 #include "breakpad/src/client/linux/minidump_writer/linux_dumper.h" 24 #include "breakpad/src/client/linux/minidump_writer/linux_dumper.h"
24 #include "breakpad/src/client/linux/minidump_writer/minidump_writer.h" 25 #include "breakpad/src/client/linux/minidump_writer/minidump_writer.h"
25 #include "chrome/app/breakpad_linux.h" 26 #include "chrome/app/breakpad_linux.h"
26 #include "chrome/browser/chrome_thread.h" 27 #include "chrome/browser/chrome_thread.h"
27 #include "chrome/common/chrome_paths.h" 28 #include "chrome/common/chrome_paths.h"
28 #include "chrome/common/env_vars.h" 29 #include "chrome/common/env_vars.h"
29 30
31 using google_breakpad::ExceptionHandler;
32
30 // Since classes derived from CrashHandlerHostLinux are singletons, it's only 33 // Since classes derived from CrashHandlerHostLinux are singletons, it's only
31 // destroyed at the end of the processes lifetime, which is greater in span than 34 // destroyed at the end of the processes lifetime, which is greater in span than
32 // the lifetime of the IO message loop. 35 // the lifetime of the IO message loop.
33 DISABLE_RUNNABLE_METHOD_REFCOUNT(CrashHandlerHostLinux); 36 DISABLE_RUNNABLE_METHOD_REFCOUNT(CrashHandlerHostLinux);
34 37
35 CrashHandlerHostLinux::CrashHandlerHostLinux() 38 CrashHandlerHostLinux::CrashHandlerHostLinux()
36 : process_socket_(-1), 39 : process_socket_(-1),
37 browser_socket_(-1) { 40 browser_socket_(-1) {
38 int fds[2]; 41 int fds[2];
39 // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the process from 42 // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the process from
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 // A process has crashed and has signaled us by writing a datagram 83 // A process has crashed and has signaled us by writing a datagram
81 // to the death signal socket. The datagram contains the crash context needed 84 // to the death signal socket. The datagram contains the crash context needed
82 // for writing the minidump as well as a file descriptor and a credentials 85 // for writing the minidump as well as a file descriptor and a credentials
83 // block so that they can't lie about their pid. 86 // block so that they can't lie about their pid.
84 87
85 // The length of the control message: 88 // The length of the control message:
86 static const unsigned kControlMsgSize = 89 static const unsigned kControlMsgSize =
87 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); 90 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
88 // The length of the regular payload: 91 // The length of the regular payload:
89 static const unsigned kCrashContextSize = 92 static const unsigned kCrashContextSize =
90 sizeof(google_breakpad::ExceptionHandler::CrashContext); 93 sizeof(ExceptionHandler::CrashContext);
91 94
92 struct msghdr msg = {0}; 95 struct msghdr msg = {0};
93 struct iovec iov[4]; 96 struct iovec iov[6];
94 char crash_context[kCrashContextSize]; 97 char crash_context[kCrashContextSize];
95 char guid[kGuidSize + 1]; 98 char guid[kGuidSize + 1];
96 char crash_url[kMaxActiveURLSize + 1]; 99 char crash_url[kMaxActiveURLSize + 1];
97 char distro[kDistroSize + 1]; 100 char distro[kDistroSize + 1];
101 char* tid_buf_addr = NULL;
102 int tid_fd = -1;
98 char control[kControlMsgSize]; 103 char control[kControlMsgSize];
99 const ssize_t expected_msg_size = sizeof(crash_context) + sizeof(guid) + 104 const ssize_t expected_msg_size = sizeof(crash_context) + sizeof(guid) +
100 sizeof(crash_url) + sizeof(distro); 105 sizeof(crash_url) + sizeof(distro) +
106 sizeof(tid_buf_addr) + sizeof(tid_fd);
101 107
102 iov[0].iov_base = crash_context; 108 iov[0].iov_base = crash_context;
103 iov[0].iov_len = sizeof(crash_context); 109 iov[0].iov_len = sizeof(crash_context);
104 iov[1].iov_base = guid; 110 iov[1].iov_base = guid;
105 iov[1].iov_len = sizeof(guid); 111 iov[1].iov_len = sizeof(guid);
106 iov[2].iov_base = crash_url; 112 iov[2].iov_base = crash_url;
107 iov[2].iov_len = sizeof(crash_url); 113 iov[2].iov_len = sizeof(crash_url);
108 iov[3].iov_base = distro; 114 iov[3].iov_base = distro;
109 iov[3].iov_len = sizeof(distro); 115 iov[3].iov_len = sizeof(distro);
116 iov[4].iov_base = &tid_buf_addr;
117 iov[4].iov_len = sizeof(tid_buf_addr);
118 iov[5].iov_base = &tid_fd;
119 iov[5].iov_len = sizeof(tid_fd);
110 msg.msg_iov = iov; 120 msg.msg_iov = iov;
111 msg.msg_iovlen = 4; 121 msg.msg_iovlen = 6;
112 msg.msg_control = control; 122 msg.msg_control = control;
113 msg.msg_controllen = kControlMsgSize; 123 msg.msg_controllen = kControlMsgSize;
114 124
115 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0)); 125 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0));
116 if (msg_size != expected_msg_size) { 126 if (msg_size != expected_msg_size) {
117 LOG(ERROR) << "Error reading from death signal socket. Crash dumping" 127 LOG(ERROR) << "Error reading from death signal socket. Crash dumping"
118 << " is disabled." 128 << " is disabled."
119 << " msg_size:" << msg_size 129 << " msg_size:" << msg_size
120 << " errno:" << errno; 130 << " errno:" << errno;
121 file_descriptor_watcher_.StopWatchingFileDescriptor(); 131 file_descriptor_watcher_.StopWatchingFileDescriptor();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 // In the future we can remove this workaround, but we have to wait a couple 186 // In the future we can remove this workaround, but we have to wait a couple
177 // of years to be sure that it's worked its way out into the world. 187 // of years to be sure that it's worked its way out into the world.
178 188
179 uint64_t inode_number; 189 uint64_t inode_number;
180 if (!base::FileDescriptorGetInode(&inode_number, signal_fd)) { 190 if (!base::FileDescriptorGetInode(&inode_number, signal_fd)) {
181 LOG(WARNING) << "Failed to get inode number for passed socket"; 191 LOG(WARNING) << "Failed to get inode number for passed socket";
182 HANDLE_EINTR(close(signal_fd)); 192 HANDLE_EINTR(close(signal_fd));
183 return; 193 return;
184 } 194 }
185 195
186 if (!base::FindProcessHoldingSocket(&crashing_pid, inode_number - 1)) { 196 pid_t actual_crashing_pid = -1;
197 if (!base::FindProcessHoldingSocket(&actual_crashing_pid, inode_number - 1)) {
187 LOG(WARNING) << "Failed to find process holding other end of crash reply " 198 LOG(WARNING) << "Failed to find process holding other end of crash reply "
188 "socket"; 199 "socket";
189 HANDLE_EINTR(close(signal_fd)); 200 HANDLE_EINTR(close(signal_fd));
190 return; 201 return;
191 } 202 }
203 if (actual_crashing_pid != crashing_pid) {
204 crashing_pid = actual_crashing_pid;
205
206 // The crashing TID set inside the compromised context via sys_gettid()
207 // in ExceptionHandler::HandleSignal is also wrong and needs to be
208 // translated.
209 //
210 // We expect the crashing thread to be in sys_read(), waiting for use to
211 // write to |signal_fd|. Most newer kernels where we have the different pid
212 // namespaces also have /proc/[pid]/syscall, so we can look through
213 // |actual_crashing_pid|'s thread group and find the thread that's in the
214 // read syscall with the right arguments.
215
216 std::string expected_syscall_data;
217 // /proc/[pid]/syscall is formatted as follows:
218 // syscall_number arg1 ... arg6 sp pc
219 // but we just check syscall_number through arg3.
220 StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ",
221 SYS_read, tid_fd, tid_buf_addr);
222 pid_t crashing_tid =
223 base::FindThreadIDWithSyscall(crashing_pid, expected_syscall_data);
224 if (crashing_tid == -1) {
225 // We didn't find the thread we want. Maybe it didn't reach sys_read()
226 // yet, or the kernel doesn't support /proc/[pid]/syscall or the thread
227 // went away. We'll just take a guess here and assume the crashing
228 // thread is the thread group leader.
229 crashing_tid = crashing_pid;
230 }
231
232 ExceptionHandler::CrashContext* bad_context =
233 reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context);
234 bad_context->tid = crashing_tid;
235 }
192 236
193 bool upload = true; 237 bool upload = true;
194 FilePath dumps_path("/tmp"); 238 FilePath dumps_path("/tmp");
195 if (getenv(env_vars::kHeadless)) { 239 if (getenv(env_vars::kHeadless)) {
196 upload = false; 240 upload = false;
197 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); 241 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
198 } 242 }
199 const uint64 rand = base::RandUint64(); 243 const uint64 rand = base::RandUint64();
200 const std::string minidump_filename = 244 const std::string minidump_filename =
201 StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp", 245 StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp",
(...skipping 29 matching lines...) Expand all
231 info.guid_length = strlen(guid); 275 info.guid_length = strlen(guid);
232 info.distro = distro; 276 info.distro = distro;
233 info.distro_length = strlen(distro); 277 info.distro_length = strlen(distro);
234 info.upload = upload; 278 info.upload = upload;
235 HandleCrashDump(info); 279 HandleCrashDump(info);
236 } 280 }
237 281
238 void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() { 282 void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() {
239 file_descriptor_watcher_.StopWatchingFileDescriptor(); 283 file_descriptor_watcher_.StopWatchingFileDescriptor();
240 } 284 }
OLDNEW
« base/linux_util.cc ('K') | « chrome/app/breakpad_linux.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698