Skip to content

Commit

Permalink
Fix RecvMsgWithPid on broken socket pair
Browse files Browse the repository at this point in the history
This prevents RecvMsgWithPid from DCHECK failing under Debug builds
when reading EOF from a broken socket pair.  Noticed while testing
crrev.com/269543014.

Unfortunately, Linux allows sending zero length messages that the
recvmsg() API does not distinguish from reading EOF.  To be
conservative, if we didn't receive any message or control bytes, then
assume we received an EOF and tolerate not knowing the sender's PID.

BUG=357670

Review URL: https://codereview.chromium.org/276593008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270967 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
mdempsky@chromium.org committed May 16, 2014
1 parent b349f9c commit d438013
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
8 changes: 7 additions & 1 deletion base/posix/unix_domain_socket_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,13 @@ ssize_t UnixDomainSocket::RecvMsgWithFlags(int fd,
}

if (out_pid) {
DCHECK(pid != -1);
// |pid| will legitimately be -1 if we read EOF, so only DCHECK if we
// actually received a message. Unfortunately, Linux allows sending zero
// length messages, which are indistinguishable from EOF, so this check
// has false negatives.
if (r > 0 || msg.msg_controllen > 0)
DCHECK_GE(pid, 0);

*out_pid = pid;
}

Expand Down
22 changes: 22 additions & 0 deletions base/posix/unix_domain_socket_linux_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,28 @@ TEST(UnixDomainSocketTest, RecvPidWithMaxDescriptors) {
ASSERT_EQ(getpid(), sender_pid);
}

// Check that RecvMsgWithPid doesn't DCHECK fail when reading EOF from a
// disconnected socket.
TEST(UnixDomianSocketTest, RecvPidDisconnectedSocket) {
int fds[2];
ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
base::ScopedFD recv_sock(fds[0]);
base::ScopedFD send_sock(fds[1]);

ASSERT_TRUE(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));

send_sock.reset();

char ch;
base::ProcessId sender_pid;
ScopedVector<base::ScopedFD> recv_fds;
const ssize_t nread = UnixDomainSocket::RecvMsgWithPid(
recv_sock.get(), &ch, sizeof(ch), &recv_fds, &sender_pid);
ASSERT_EQ(0, nread);
ASSERT_EQ(-1, sender_pid);
ASSERT_EQ(0U, recv_fds.size());
}

} // namespace

} // namespace base

0 comments on commit d438013

Please sign in to comment.