| Index: components/breakpad/browser/crash_handler_host_linux.cc
|
| ===================================================================
|
| --- components/breakpad/browser/crash_handler_host_linux.cc (revision 275009)
|
| +++ components/breakpad/browser/crash_handler_host_linux.cc (working copy)
|
| @@ -14,6 +14,7 @@
|
| #include "base/bind_helpers.h"
|
| #include "base/file_util.h"
|
| #include "base/files/file_path.h"
|
| +#include "base/files/scoped_file.h"
|
| #include "base/format_macros.h"
|
| #include "base/linux_util.h"
|
| #include "base/logging.h"
|
| @@ -195,7 +196,7 @@
|
| msg.msg_controllen = kControlMsgSize;
|
|
|
| const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0));
|
| - if (msg_size != expected_msg_size) {
|
| + if (msg_size < 0) {
|
| LOG(ERROR) << "Error reading from death signal socket. Crash dumping"
|
| << " is disabled."
|
| << " msg_size:" << msg_size
|
| @@ -203,9 +204,46 @@
|
| file_descriptor_watcher_.StopWatchingFileDescriptor();
|
| return;
|
| }
|
| + const bool bad_message = (msg_size != expected_msg_size ||
|
| + msg.msg_controllen != kControlMsgSize ||
|
| + msg.msg_flags & ~MSG_TRUNC);
|
| + base::ScopedFD signal_fd;
|
| + pid_t crashing_pid = -1;
|
| + if (msg.msg_controllen > 0) {
|
| + // Walk the control payload and extract the file descriptor and
|
| + // validated pid.
|
| + for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr;
|
| + hdr = CMSG_NXTHDR(&msg, hdr)) {
|
| + if (hdr->cmsg_level != SOL_SOCKET)
|
| + continue;
|
| + if (hdr->cmsg_type == SCM_RIGHTS) {
|
| + const size_t len = hdr->cmsg_len -
|
| + (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
|
| + DCHECK_EQ(0U, len % sizeof(int));
|
| + const size_t num_fds = len / sizeof(int);
|
| + if (num_fds != kNumFDs) {
|
| + // A nasty process could try and send us too many descriptors and
|
| + // force a leak.
|
| + LOG(ERROR) << "Death signal contained wrong number of descriptors;"
|
| + << " num_fds:" << num_fds;
|
| + for (size_t i = 0; i < num_fds; ++i)
|
| + close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]);
|
| + return;
|
| + }
|
| + DCHECK(!signal_fd.is_valid());
|
| + int fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0];
|
| + DCHECK_GE(fd, 0); // The kernel should never send a negative fd.
|
| + signal_fd.reset(fd);
|
| + } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
|
| + DCHECK_EQ(-1, crashing_pid);
|
| + const struct ucred *cred =
|
| + reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
|
| + crashing_pid = cred->pid;
|
| + }
|
| + }
|
| + }
|
|
|
| - if (msg.msg_controllen != kControlMsgSize ||
|
| - msg.msg_flags & ~MSG_TRUNC) {
|
| + if (bad_message) {
|
| LOG(ERROR) << "Received death signal message with the wrong size;"
|
| << " msg.msg_controllen:" << msg.msg_controllen
|
| << " msg.msg_flags:" << msg.msg_flags
|
| @@ -213,42 +251,9 @@
|
| << " kControlMsgSize:" << kControlMsgSize;
|
| return;
|
| }
|
| -
|
| - // Walk the control payload an extract the file descriptor and validated pid.
|
| - pid_t crashing_pid = -1;
|
| - int signal_fd = -1;
|
| - for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr;
|
| - hdr = CMSG_NXTHDR(&msg, hdr)) {
|
| - if (hdr->cmsg_level != SOL_SOCKET)
|
| - continue;
|
| - if (hdr->cmsg_type == SCM_RIGHTS) {
|
| - const size_t len = hdr->cmsg_len -
|
| - (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
|
| - DCHECK_EQ(0U, len % sizeof(int));
|
| - const size_t num_fds = len / sizeof(int);
|
| - if (num_fds != kNumFDs) {
|
| - // A nasty process could try and send us too many descriptors and
|
| - // force a leak.
|
| - LOG(ERROR) << "Death signal contained wrong number of descriptors;"
|
| - << " num_fds:" << num_fds;
|
| - for (size_t i = 0; i < num_fds; ++i)
|
| - close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]);
|
| - return;
|
| - } else {
|
| - signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0];
|
| - }
|
| - } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
|
| - const struct ucred *cred =
|
| - reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
|
| - crashing_pid = cred->pid;
|
| - }
|
| - }
|
| -
|
| - if (crashing_pid == -1 || signal_fd == -1) {
|
| + if (crashing_pid == -1 || !signal_fd.is_valid()) {
|
| LOG(ERROR) << "Death signal message didn't contain all expected control"
|
| << " messages";
|
| - if (signal_fd >= 0)
|
| - close(signal_fd);
|
| return;
|
| }
|
|
|
| @@ -326,7 +331,7 @@
|
| base::Passed(&info),
|
| base::Passed(&crash_context),
|
| crashing_pid,
|
| - signal_fd));
|
| + signal_fd.release()));
|
| }
|
|
|
| void CrashHandlerHostLinux::WriteDumpFile(scoped_ptr<BreakpadInfo> info,
|
|
|