Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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 "ipc/ipc_channel_posix.h" | 5 #include "ipc/ipc_channel_posix.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 #include <sys/types.h> | 10 #include <sys/types.h> |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, | 266 Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, |
| 267 Listener* listener) | 267 Listener* listener) |
| 268 : mode_(mode), | 268 : mode_(mode), |
| 269 is_blocked_on_write_(false), | 269 is_blocked_on_write_(false), |
| 270 message_send_bytes_written_(0), | 270 message_send_bytes_written_(0), |
| 271 uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch( | 271 uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch( |
| 272 switches::kIPCUseFIFO)), | 272 switches::kIPCUseFIFO)), |
| 273 server_listen_pipe_(-1), | 273 server_listen_pipe_(-1), |
| 274 pipe_(-1), | 274 pipe_(-1), |
| 275 client_pipe_(-1), | 275 client_pipe_(-1), |
| 276 #if defined(OS_LINUX) | 276 #if !defined(OS_MACOSX) |
| 277 fd_pipe_(-1), | 277 fd_pipe_(-1), |
| 278 remote_fd_pipe_(-1), | 278 remote_fd_pipe_(-1), |
| 279 #endif | 279 #endif |
| 280 listener_(listener), | 280 listener_(listener), |
| 281 waiting_connect_(true), | 281 waiting_connect_(true), |
| 282 factory_(this) { | 282 factory_(this) { |
| 283 if (!CreatePipe(channel_id, mode)) { | 283 if (!CreatePipe(channel_id, mode)) { |
| 284 // The pipe may have been closed already. | 284 // The pipe may have been closed already. |
| 285 PLOG(WARNING) << "Unable to create pipe named \"" << channel_id | 285 PLOG(WARNING) << "Unable to create pipe named \"" << channel_id |
| 286 << "\" in " << (mode == MODE_SERVER ? "server" : "client") | 286 << "\" in " << (mode == MODE_SERVER ? "server" : "client") |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 } | 377 } |
| 378 } else { | 378 } else { |
| 379 waiting_connect_ = mode == MODE_SERVER; | 379 waiting_connect_ = mode == MODE_SERVER; |
| 380 } | 380 } |
| 381 } | 381 } |
| 382 | 382 |
| 383 // Create the Hello message to be sent when Connect is called | 383 // Create the Hello message to be sent when Connect is called |
| 384 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | 384 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, |
| 385 HELLO_MESSAGE_TYPE, | 385 HELLO_MESSAGE_TYPE, |
| 386 IPC::Message::PRIORITY_NORMAL)); | 386 IPC::Message::PRIORITY_NORMAL)); |
| 387 #if defined(OS_LINUX) | 387 #if !defined(OS_MACOSX) |
| 388 if (!uses_fifo_) { | 388 if (!uses_fifo_) { |
| 389 // On Linux, the seccomp sandbox makes it very expensive to call | 389 // On Linux, the seccomp sandbox makes it very expensive to call |
| 390 // recvmsg() and sendmsg(). Often, we are perfectly OK with resorting to | 390 // recvmsg() and sendmsg(). Often, we are perfectly OK with resorting to |
| 391 // read() and write(), which are cheap. | 391 // read() and write(), which are cheap. |
| 392 // | 392 // |
| 393 // As we cannot anticipate, when the sender will provide us with file | 393 // As we cannot anticipate, when the sender will provide us with file |
| 394 // handles, we have to make the decision about whether we call read() or | 394 // handles, we have to make the decision about whether we call read() or |
| 395 // recvmsg() before we actually make the call. The easiest option is to | 395 // recvmsg() before we actually make the call. The easiest option is to |
| 396 // create a dedicated socketpair() for exchanging file handles. | 396 // create a dedicated socketpair() for exchanging file handles. |
| 397 if (mode == MODE_SERVER) { | 397 if (mode == MODE_SERVER) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 453 for (;;) { | 453 for (;;) { |
| 454 msg.msg_iov = &iov; | 454 msg.msg_iov = &iov; |
| 455 | 455 |
| 456 if (bytes_read == 0) { | 456 if (bytes_read == 0) { |
| 457 if (pipe_ == -1) | 457 if (pipe_ == -1) |
| 458 return false; | 458 return false; |
| 459 | 459 |
| 460 // Read from pipe. | 460 // Read from pipe. |
| 461 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | 461 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data |
| 462 // is waiting on the pipe. | 462 // is waiting on the pipe. |
| 463 #if defined(OS_LINUX) | 463 #if !defined(OS_MACOSX) |
| 464 if (fd_pipe_ >= 0) { | 464 if (fd_pipe_ >= 0) { |
| 465 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_, | 465 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_, |
| 466 Channel::kReadBufferSize)); | 466 Channel::kReadBufferSize)); |
| 467 msg.msg_controllen = 0; | 467 msg.msg_controllen = 0; |
| 468 } else | 468 } else |
| 469 #endif | 469 #endif |
| 470 { | 470 { |
| 471 msg.msg_controllen = sizeof(input_cmsg_buf_); | 471 msg.msg_controllen = sizeof(input_cmsg_buf_); |
| 472 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); | 472 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); |
| 473 } | 473 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 585 if (message_tail) { | 585 if (message_tail) { |
| 586 int len = static_cast<int>(message_tail - p); | 586 int len = static_cast<int>(message_tail - p); |
| 587 Message m(p, len); | 587 Message m(p, len); |
| 588 | 588 |
| 589 if (m.header()->num_fds) { | 589 if (m.header()->num_fds) { |
| 590 // the message has file descriptors | 590 // the message has file descriptors |
| 591 const char* error = NULL; | 591 const char* error = NULL; |
| 592 if (m.header()->num_fds > num_fds - fds_i) { | 592 if (m.header()->num_fds > num_fds - fds_i) { |
| 593 // the message has been completely received, but we didn't get | 593 // the message has been completely received, but we didn't get |
| 594 // enough file descriptors. | 594 // enough file descriptors. |
| 595 #if defined(OS_LINUX) | 595 #if !defined(OS_MACOSX) |
| 596 if (!uses_fifo_) { | 596 if (!uses_fifo_) { |
| 597 char dummy; | 597 char dummy; |
| 598 struct iovec fd_pipe_iov = { &dummy, 1 }; | 598 struct iovec fd_pipe_iov = { &dummy, 1 }; |
| 599 msg.msg_iov = &fd_pipe_iov; | 599 msg.msg_iov = &fd_pipe_iov; |
| 600 msg.msg_controllen = sizeof(input_cmsg_buf_); | 600 msg.msg_controllen = sizeof(input_cmsg_buf_); |
| 601 ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); | 601 ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); |
| 602 if (n == 1 && msg.msg_controllen > 0) { | 602 if (n == 1 && msg.msg_controllen > 0) { |
| 603 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; | 603 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; |
| 604 cmsg = CMSG_NXTHDR(&msg, cmsg)) { | 604 cmsg = CMSG_NXTHDR(&msg, cmsg)) { |
| 605 if (cmsg->cmsg_level == SOL_SOCKET && | 605 if (cmsg->cmsg_level == SOL_SOCKET && |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 " with type " << m.type(); | 675 " with type " << m.type(); |
| 676 #endif | 676 #endif |
| 677 if (m.routing_id() == MSG_ROUTING_NONE && | 677 if (m.routing_id() == MSG_ROUTING_NONE && |
| 678 m.type() == HELLO_MESSAGE_TYPE) { | 678 m.type() == HELLO_MESSAGE_TYPE) { |
| 679 // The Hello message contains only the process id. | 679 // The Hello message contains only the process id. |
| 680 void *iter = NULL; | 680 void *iter = NULL; |
| 681 int pid; | 681 int pid; |
| 682 if (!m.ReadInt(&iter, &pid)) { | 682 if (!m.ReadInt(&iter, &pid)) { |
| 683 NOTREACHED(); | 683 NOTREACHED(); |
| 684 } | 684 } |
| 685 #if defined(OS_LINUX) | 685 #if !defined(OS_MACOSX) |
| 686 if (mode_ == MODE_SERVER && !uses_fifo_) { | 686 if (mode_ == MODE_SERVER && !uses_fifo_) { |
| 687 // On Linux, the Hello message from the client to the server | 687 // On Linux, the Hello message from the client to the server |
|
Evan Martin
2010/05/19 11:50:11
s/Linux/non-Mac/
| |
| 688 // also contains the fd_pipe_, which will be used for all | 688 // also contains the fd_pipe_, which will be used for all |
| 689 // subsequent file descriptor passing. | 689 // subsequent file descriptor passing. |
| 690 DCHECK_EQ(m.file_descriptor_set()->size(), 1); | 690 DCHECK_EQ(m.file_descriptor_set()->size(), 1); |
| 691 base::FileDescriptor descriptor; | 691 base::FileDescriptor descriptor; |
| 692 if (!m.ReadFileDescriptor(&iter, &descriptor)) { | 692 if (!m.ReadFileDescriptor(&iter, &descriptor)) { |
| 693 NOTREACHED(); | 693 NOTREACHED(); |
| 694 } | 694 } |
| 695 fd_pipe_ = descriptor.fd; | 695 fd_pipe_ = descriptor.fd; |
| 696 CHECK(descriptor.auto_close); | 696 CHECK(descriptor.auto_close); |
| 697 } | 697 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 738 | 738 |
| 739 if (pipe_ == -1) { | 739 if (pipe_ == -1) { |
| 740 return false; | 740 return false; |
| 741 } | 741 } |
| 742 | 742 |
| 743 // Write out all the messages we can till the write blocks or there are no | 743 // Write out all the messages we can till the write blocks or there are no |
| 744 // more outgoing messages. | 744 // more outgoing messages. |
| 745 while (!output_queue_.empty()) { | 745 while (!output_queue_.empty()) { |
| 746 Message* msg = output_queue_.front(); | 746 Message* msg = output_queue_.front(); |
| 747 | 747 |
| 748 #if defined(OS_LINUX) | 748 #if !defined(OS_MACOSX) |
| 749 scoped_ptr<Message> hello; | 749 scoped_ptr<Message> hello; |
| 750 if (remote_fd_pipe_ != -1 && | 750 if (remote_fd_pipe_ != -1 && |
| 751 msg->routing_id() == MSG_ROUTING_NONE && | 751 msg->routing_id() == MSG_ROUTING_NONE && |
| 752 msg->type() == HELLO_MESSAGE_TYPE) { | 752 msg->type() == HELLO_MESSAGE_TYPE) { |
| 753 hello.reset(new Message(MSG_ROUTING_NONE, | 753 hello.reset(new Message(MSG_ROUTING_NONE, |
| 754 HELLO_MESSAGE_TYPE, | 754 HELLO_MESSAGE_TYPE, |
| 755 IPC::Message::PRIORITY_NORMAL)); | 755 IPC::Message::PRIORITY_NORMAL)); |
| 756 void* iter = NULL; | 756 void* iter = NULL; |
| 757 int pid; | 757 int pid; |
| 758 if (!msg->ReadInt(&iter, &pid) || | 758 if (!msg->ReadInt(&iter, &pid) || |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 799 cmsg->cmsg_type = SCM_RIGHTS; | 799 cmsg->cmsg_type = SCM_RIGHTS; |
| 800 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | 800 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); |
| 801 msg->file_descriptor_set()->GetDescriptors( | 801 msg->file_descriptor_set()->GetDescriptors( |
| 802 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | 802 reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
| 803 msgh.msg_controllen = cmsg->cmsg_len; | 803 msgh.msg_controllen = cmsg->cmsg_len; |
| 804 | 804 |
| 805 // DCHECK_LE above already checks that | 805 // DCHECK_LE above already checks that |
| 806 // num_fds < MAX_DESCRIPTORS_PER_MESSAGE so no danger of overflow. | 806 // num_fds < MAX_DESCRIPTORS_PER_MESSAGE so no danger of overflow. |
| 807 msg->header()->num_fds = static_cast<uint16>(num_fds); | 807 msg->header()->num_fds = static_cast<uint16>(num_fds); |
| 808 | 808 |
| 809 #if defined(OS_LINUX) | 809 #if !defined(OS_MACOSX) |
| 810 if (!uses_fifo_ && | 810 if (!uses_fifo_ && |
| 811 (msg->routing_id() != MSG_ROUTING_NONE || | 811 (msg->routing_id() != MSG_ROUTING_NONE || |
| 812 msg->type() != HELLO_MESSAGE_TYPE)) { | 812 msg->type() != HELLO_MESSAGE_TYPE)) { |
| 813 // Only the Hello message sends the file descriptor with the message. | 813 // Only the Hello message sends the file descriptor with the message. |
| 814 // Subsequently, we can send file descriptors on the dedicated | 814 // Subsequently, we can send file descriptors on the dedicated |
| 815 // fd_pipe_ which makes Seccomp sandbox operation more efficient. | 815 // fd_pipe_ which makes Seccomp sandbox operation more efficient. |
| 816 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; | 816 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; |
| 817 msgh.msg_iov = &fd_pipe_iov; | 817 msgh.msg_iov = &fd_pipe_iov; |
| 818 fd_written = fd_pipe_; | 818 fd_written = fd_pipe_; |
| 819 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); | 819 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); |
| 820 msgh.msg_iov = &iov; | 820 msgh.msg_iov = &iov; |
| 821 msgh.msg_controllen = 0; | 821 msgh.msg_controllen = 0; |
| 822 if (bytes_written > 0) { | 822 if (bytes_written > 0) { |
| 823 msg->file_descriptor_set()->CommitAll(); | 823 msg->file_descriptor_set()->CommitAll(); |
| 824 } | 824 } |
| 825 } | 825 } |
| 826 #endif | 826 #endif |
| 827 } | 827 } |
| 828 | 828 |
| 829 if (bytes_written == 1) { | 829 if (bytes_written == 1) { |
| 830 fd_written = pipe_; | 830 fd_written = pipe_; |
| 831 #if defined(OS_LINUX) | 831 #if !defined(OS_MACOSX) |
| 832 if (mode_ != MODE_SERVER && !uses_fifo_ && | 832 if (mode_ != MODE_SERVER && !uses_fifo_ && |
| 833 msg->routing_id() == MSG_ROUTING_NONE && | 833 msg->routing_id() == MSG_ROUTING_NONE && |
| 834 msg->type() == HELLO_MESSAGE_TYPE) { | 834 msg->type() == HELLO_MESSAGE_TYPE) { |
| 835 DCHECK_EQ(msg->file_descriptor_set()->size(), 1); | 835 DCHECK_EQ(msg->file_descriptor_set()->size(), 1); |
| 836 } | 836 } |
| 837 if (!uses_fifo_ && !msgh.msg_controllen) { | 837 if (!uses_fifo_ && !msgh.msg_controllen) { |
| 838 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); | 838 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); |
| 839 } else | 839 } else |
| 840 #endif | 840 #endif |
| 841 { | 841 { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 992 read_watcher_.StopWatchingFileDescriptor(); | 992 read_watcher_.StopWatchingFileDescriptor(); |
| 993 write_watcher_.StopWatchingFileDescriptor(); | 993 write_watcher_.StopWatchingFileDescriptor(); |
| 994 if (pipe_ != -1) { | 994 if (pipe_ != -1) { |
| 995 HANDLE_EINTR(close(pipe_)); | 995 HANDLE_EINTR(close(pipe_)); |
| 996 pipe_ = -1; | 996 pipe_ = -1; |
| 997 } | 997 } |
| 998 if (client_pipe_ != -1) { | 998 if (client_pipe_ != -1) { |
| 999 Singleton<PipeMap>()->RemoveAndClose(pipe_name_); | 999 Singleton<PipeMap>()->RemoveAndClose(pipe_name_); |
| 1000 client_pipe_ = -1; | 1000 client_pipe_ = -1; |
| 1001 } | 1001 } |
| 1002 #if defined(OS_LINUX) | 1002 #if !defined(OS_MACOSX) |
| 1003 if (fd_pipe_ != -1) { | 1003 if (fd_pipe_ != -1) { |
| 1004 HANDLE_EINTR(close(fd_pipe_)); | 1004 HANDLE_EINTR(close(fd_pipe_)); |
| 1005 fd_pipe_ = -1; | 1005 fd_pipe_ = -1; |
| 1006 } | 1006 } |
| 1007 if (remote_fd_pipe_ != -1) { | 1007 if (remote_fd_pipe_ != -1) { |
| 1008 HANDLE_EINTR(close(remote_fd_pipe_)); | 1008 HANDLE_EINTR(close(remote_fd_pipe_)); |
| 1009 remote_fd_pipe_ = -1; | 1009 remote_fd_pipe_ = -1; |
| 1010 } | 1010 } |
| 1011 #endif | 1011 #endif |
| 1012 | 1012 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1054 | 1054 |
| 1055 bool Channel::Send(Message* message) { | 1055 bool Channel::Send(Message* message) { |
| 1056 return channel_impl_->Send(message); | 1056 return channel_impl_->Send(message); |
| 1057 } | 1057 } |
| 1058 | 1058 |
| 1059 int Channel::GetClientFileDescriptor() const { | 1059 int Channel::GetClientFileDescriptor() const { |
| 1060 return channel_impl_->GetClientFileDescriptor(); | 1060 return channel_impl_->GetClientFileDescriptor(); |
| 1061 } | 1061 } |
| 1062 | 1062 |
| 1063 } // namespace IPC | 1063 } // namespace IPC |
| OLD | NEW |