summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-12 02:39:31 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-12 02:39:31 +0000
commitafb4bad25473e8bd8b310096c70d404b06765314 (patch)
treeb55bd8bb99869535beacb2da2cc316c291a396b5 /chrome/common
parentf8bae45bba9bfc60577e189c13dd18d91ac2642a (diff)
downloadchromium_src-afb4bad25473e8bd8b310096c70d404b06765314.zip
chromium_src-afb4bad25473e8bd8b310096c70d404b06765314.tar.gz
chromium_src-afb4bad25473e8bd8b310096c70d404b06765314.tar.bz2
OSX: Workaround CMSG_FIRSTHDR bug
On OSX, CMSG_FIRSTHDR will return a pointer into the control buffer space when controllen == 0. We work around by testing for a non-zero controllen before trying to parse control messages. Test case: int main() { struct msghdr msg; msg.msg_control = &msg; msg.msg_controllen = 0; if (CMSG_FIRSTHDR(&msg)) printf("Bug found!\n"); } Review URL: http://codereview.chromium.org/21283 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9640 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/ipc_channel_posix.cc58
1 files changed, 41 insertions, 17 deletions
diff --git a/chrome/common/ipc_channel_posix.cc b/chrome/common/ipc_channel_posix.cc
index d9f44dd..b46024c 100644
--- a/chrome/common/ipc_channel_posix.cc
+++ b/chrome/common/ipc_channel_posix.cc
@@ -406,24 +406,40 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() {
// walk the list of control messages and, if we find an array of file
// descriptors, save a pointer to the array
- for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
- DCHECK(payload_len % sizeof(int) == 0);
- wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
- num_wire_fds = payload_len / 4;
-
- if (msg.msg_flags & MSG_CTRUNC) {
- LOG(ERROR) << "SCM_RIGHTS message was truncated"
- << " cmsg_len:" << cmsg->cmsg_len
- << " fd:" << pipe_;
- for (unsigned i = 0; i < num_wire_fds; ++i)
- close(wire_fds[i]);
- return false;
+
+ // This next if statement is to work around an OSX issue where
+ // CMSG_FIRSTHDR will return non-NULL in the case that controllen == 0.
+ // Here's a test case:
+ //
+ // int main() {
+ // struct msghdr msg;
+ // msg.msg_control = &msg;
+ // msg.msg_controllen = 0;
+ // if (CMSG_FIRSTHDR(&msg))
+ // printf("Bug found!\n");
+ // }
+ if (msg.msg_controllen > 0) {
+ // On OSX, CMSG_FIRSTHDR doesn't handle the case where controllen is 0
+ // and will return a pointer into nowhere.
+ for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_RIGHTS) {
+ const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
+ DCHECK(payload_len % sizeof(int) == 0);
+ wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+ num_wire_fds = payload_len / 4;
+
+ if (msg.msg_flags & MSG_CTRUNC) {
+ LOG(ERROR) << "SCM_RIGHTS message was truncated"
+ << " cmsg_len:" << cmsg->cmsg_len
+ << " fd:" << pipe_;
+ for (unsigned i = 0; i < num_wire_fds; ++i)
+ close(wire_fds[i]);
+ return false;
+ }
+ break;
}
- break;
}
}
@@ -509,6 +525,14 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() {
input_overflow_buf_.assign(p, end - p);
input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]);
+ // When the input data buffer is empty, the overflow fds should be too. If
+ // this is not the case, we probably have a rogue renderer which is trying
+ // to fill our descriptor table.
+ if (input_overflow_buf_.empty() && !input_overflow_fds_.empty()) {
+ // We close these descriptors in Close()
+ return false;
+ }
+
bytes_read = 0; // Get more data.
}