| OLD | NEW |
| 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 "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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 Listener* listener) | 278 Listener* listener) |
| 279 : mode_(mode), | 279 : mode_(mode), |
| 280 is_blocked_on_write_(false), | 280 is_blocked_on_write_(false), |
| 281 message_send_bytes_written_(0), | 281 message_send_bytes_written_(0), |
| 282 uses_fifo_( | 282 uses_fifo_( |
| 283 CommandLine::ForCurrentProcess()->HasSwitch(switches::kIPCUseFIFO) || | 283 CommandLine::ForCurrentProcess()->HasSwitch(switches::kIPCUseFIFO) || |
| 284 mode == MODE_NAMED_SERVER || mode == MODE_NAMED_CLIENT), | 284 mode == MODE_NAMED_SERVER || mode == MODE_NAMED_CLIENT), |
| 285 server_listen_pipe_(-1), | 285 server_listen_pipe_(-1), |
| 286 pipe_(-1), | 286 pipe_(-1), |
| 287 client_pipe_(-1), | 287 client_pipe_(-1), |
| 288 #if !defined(OS_MACOSX) | 288 #if defined(IPC_USES_READWRITE) |
| 289 fd_pipe_(-1), | 289 fd_pipe_(-1), |
| 290 remote_fd_pipe_(-1), | 290 remote_fd_pipe_(-1), |
| 291 #endif | 291 #endif |
| 292 listener_(listener), | 292 listener_(listener), |
| 293 waiting_connect_(true), | 293 waiting_connect_(true), |
| 294 factory_(this) { | 294 factory_(this) { |
| 295 if (mode_ == MODE_NAMED_SERVER) | 295 if (mode_ == MODE_NAMED_SERVER) |
| 296 mode_ = MODE_SERVER; | 296 mode_ = MODE_SERVER; |
| 297 if (mode_ == MODE_NAMED_CLIENT) | 297 if (mode_ == MODE_NAMED_CLIENT) |
| 298 mode_ = MODE_CLIENT; | 298 mode_ = MODE_CLIENT; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 } | 400 } |
| 401 } else { | 401 } else { |
| 402 waiting_connect_ = mode == MODE_SERVER; | 402 waiting_connect_ = mode == MODE_SERVER; |
| 403 } | 403 } |
| 404 } | 404 } |
| 405 | 405 |
| 406 // Create the Hello message to be sent when Connect is called | 406 // Create the Hello message to be sent when Connect is called |
| 407 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | 407 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, |
| 408 HELLO_MESSAGE_TYPE, | 408 HELLO_MESSAGE_TYPE, |
| 409 IPC::Message::PRIORITY_NORMAL)); | 409 IPC::Message::PRIORITY_NORMAL)); |
| 410 #if !defined(OS_MACOSX) | 410 #if defined(IPC_USES_READWRITE) |
| 411 if (!uses_fifo_) { | 411 if (!uses_fifo_) { |
| 412 // On Linux, the seccomp sandbox makes it very expensive to call | 412 // Create a dedicated socketpair() for exchanging file descriptors. |
| 413 // recvmsg() and sendmsg(). Often, we are perfectly OK with resorting to | 413 // See comments for IPC_USES_READWRITE for details. |
| 414 // read() and write(), which are cheap. | |
| 415 // | |
| 416 // As we cannot anticipate, when the sender will provide us with file | |
| 417 // handles, we have to make the decision about whether we call read() or | |
| 418 // recvmsg() before we actually make the call. The easiest option is to | |
| 419 // create a dedicated socketpair() for exchanging file handles. | |
| 420 if (mode == MODE_SERVER) { | 414 if (mode == MODE_SERVER) { |
| 421 fd_pipe_ = -1; | 415 fd_pipe_ = -1; |
| 422 } else if (remote_fd_pipe_ == -1) { | 416 } else if (remote_fd_pipe_ == -1) { |
| 423 if (!SocketPair(&fd_pipe_, &remote_fd_pipe_)) { | 417 if (!SocketPair(&fd_pipe_, &remote_fd_pipe_)) { |
| 424 return false; | 418 return false; |
| 425 } | 419 } |
| 426 } | 420 } |
| 427 } | 421 } |
| 428 #endif | 422 #endif |
| 429 if (!msg->WriteInt(base::GetCurrentProcId())) { | 423 if (!msg->WriteInt(base::GetCurrentProcId())) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 for (;;) { | 470 for (;;) { |
| 477 msg.msg_iov = &iov; | 471 msg.msg_iov = &iov; |
| 478 | 472 |
| 479 if (bytes_read == 0) { | 473 if (bytes_read == 0) { |
| 480 if (pipe_ == -1) | 474 if (pipe_ == -1) |
| 481 return false; | 475 return false; |
| 482 | 476 |
| 483 // Read from pipe. | 477 // Read from pipe. |
| 484 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | 478 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data |
| 485 // is waiting on the pipe. | 479 // is waiting on the pipe. |
| 486 #if !defined(OS_MACOSX) | 480 #if defined(IPC_USES_READWRITE) |
| 487 if (fd_pipe_ >= 0) { | 481 if (fd_pipe_ >= 0) { |
| 488 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_, | 482 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_, |
| 489 Channel::kReadBufferSize)); | 483 Channel::kReadBufferSize)); |
| 490 msg.msg_controllen = 0; | 484 msg.msg_controllen = 0; |
| 491 } else | 485 } else |
| 492 #endif | 486 #endif |
| 493 { | 487 { |
| 494 msg.msg_controllen = sizeof(input_cmsg_buf_); | 488 msg.msg_controllen = sizeof(input_cmsg_buf_); |
| 495 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); | 489 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); |
| 496 } | 490 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 if (message_tail) { | 603 if (message_tail) { |
| 610 int len = static_cast<int>(message_tail - p); | 604 int len = static_cast<int>(message_tail - p); |
| 611 Message m(p, len); | 605 Message m(p, len); |
| 612 | 606 |
| 613 if (m.header()->num_fds) { | 607 if (m.header()->num_fds) { |
| 614 // the message has file descriptors | 608 // the message has file descriptors |
| 615 const char* error = NULL; | 609 const char* error = NULL; |
| 616 if (m.header()->num_fds > num_fds - fds_i) { | 610 if (m.header()->num_fds > num_fds - fds_i) { |
| 617 // the message has been completely received, but we didn't get | 611 // the message has been completely received, but we didn't get |
| 618 // enough file descriptors. | 612 // enough file descriptors. |
| 619 #if !defined(OS_MACOSX) | 613 #if defined(IPC_USES_READWRITE) |
| 620 if (!uses_fifo_) { | 614 if (!uses_fifo_) { |
| 621 char dummy; | 615 char dummy; |
| 622 struct iovec fd_pipe_iov = { &dummy, 1 }; | 616 struct iovec fd_pipe_iov = { &dummy, 1 }; |
| 623 msg.msg_iov = &fd_pipe_iov; | 617 msg.msg_iov = &fd_pipe_iov; |
| 624 msg.msg_controllen = sizeof(input_cmsg_buf_); | 618 msg.msg_controllen = sizeof(input_cmsg_buf_); |
| 625 ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); | 619 ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); |
| 626 if (n == 1 && msg.msg_controllen > 0) { | 620 if (n == 1 && msg.msg_controllen > 0) { |
| 627 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; | 621 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; |
| 628 cmsg = CMSG_NXTHDR(&msg, cmsg)) { | 622 cmsg = CMSG_NXTHDR(&msg, cmsg)) { |
| 629 if (cmsg->cmsg_level == SOL_SOCKET && | 623 if (cmsg->cmsg_level == SOL_SOCKET && |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 DVLOG(2) << "received message on channel @" << this | 693 DVLOG(2) << "received message on channel @" << this |
| 700 << " with type " << m.type(); | 694 << " with type " << m.type(); |
| 701 if (m.routing_id() == MSG_ROUTING_NONE && | 695 if (m.routing_id() == MSG_ROUTING_NONE && |
| 702 m.type() == HELLO_MESSAGE_TYPE) { | 696 m.type() == HELLO_MESSAGE_TYPE) { |
| 703 // The Hello message contains only the process id. | 697 // The Hello message contains only the process id. |
| 704 void *iter = NULL; | 698 void *iter = NULL; |
| 705 int pid; | 699 int pid; |
| 706 if (!m.ReadInt(&iter, &pid)) { | 700 if (!m.ReadInt(&iter, &pid)) { |
| 707 NOTREACHED(); | 701 NOTREACHED(); |
| 708 } | 702 } |
| 709 #if !defined(OS_MACOSX) | 703 #if defined(IPC_USES_READWRITE) |
| 710 if (mode_ == MODE_SERVER && !uses_fifo_) { | 704 if (mode_ == MODE_SERVER && !uses_fifo_) { |
| 711 // On non-Mac, the Hello message from the client to the server | 705 // On non-Mac, the Hello message from the client to the server |
| 712 // also contains the fd_pipe_, which will be used for all | 706 // also contains the fd_pipe_, which will be used for all |
| 713 // subsequent file descriptor passing. | 707 // subsequent file descriptor passing. |
| 714 DCHECK_EQ(m.file_descriptor_set()->size(), 1U); | 708 DCHECK_EQ(m.file_descriptor_set()->size(), 1U); |
| 715 base::FileDescriptor descriptor; | 709 base::FileDescriptor descriptor; |
| 716 if (!m.ReadFileDescriptor(&iter, &descriptor)) { | 710 if (!m.ReadFileDescriptor(&iter, &descriptor)) { |
| 717 NOTREACHED(); | 711 NOTREACHED(); |
| 718 } | 712 } |
| 719 fd_pipe_ = descriptor.fd; | 713 fd_pipe_ = descriptor.fd; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 | 756 |
| 763 if (pipe_ == -1) { | 757 if (pipe_ == -1) { |
| 764 return false; | 758 return false; |
| 765 } | 759 } |
| 766 | 760 |
| 767 // Write out all the messages we can till the write blocks or there are no | 761 // Write out all the messages we can till the write blocks or there are no |
| 768 // more outgoing messages. | 762 // more outgoing messages. |
| 769 while (!output_queue_.empty()) { | 763 while (!output_queue_.empty()) { |
| 770 Message* msg = output_queue_.front(); | 764 Message* msg = output_queue_.front(); |
| 771 | 765 |
| 772 #if !defined(OS_MACOSX) | 766 #if defined(IPC_USES_READWRITE) |
| 773 scoped_ptr<Message> hello; | 767 scoped_ptr<Message> hello; |
| 774 if (remote_fd_pipe_ != -1 && | 768 if (remote_fd_pipe_ != -1 && |
| 775 msg->routing_id() == MSG_ROUTING_NONE && | 769 msg->routing_id() == MSG_ROUTING_NONE && |
| 776 msg->type() == HELLO_MESSAGE_TYPE) { | 770 msg->type() == HELLO_MESSAGE_TYPE) { |
| 777 hello.reset(new Message(MSG_ROUTING_NONE, | 771 hello.reset(new Message(MSG_ROUTING_NONE, |
| 778 HELLO_MESSAGE_TYPE, | 772 HELLO_MESSAGE_TYPE, |
| 779 IPC::Message::PRIORITY_NORMAL)); | 773 IPC::Message::PRIORITY_NORMAL)); |
| 780 void* iter = NULL; | 774 void* iter = NULL; |
| 781 int pid; | 775 int pid; |
| 782 if (!msg->ReadInt(&iter, &pid) || | 776 if (!msg->ReadInt(&iter, &pid) || |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 cmsg->cmsg_type = SCM_RIGHTS; | 826 cmsg->cmsg_type = SCM_RIGHTS; |
| 833 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | 827 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); |
| 834 msg->file_descriptor_set()->GetDescriptors( | 828 msg->file_descriptor_set()->GetDescriptors( |
| 835 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | 829 reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
| 836 msgh.msg_controllen = cmsg->cmsg_len; | 830 msgh.msg_controllen = cmsg->cmsg_len; |
| 837 | 831 |
| 838 // DCHECK_LE above already checks that | 832 // DCHECK_LE above already checks that |
| 839 // num_fds < MAX_DESCRIPTORS_PER_MESSAGE so no danger of overflow. | 833 // num_fds < MAX_DESCRIPTORS_PER_MESSAGE so no danger of overflow. |
| 840 msg->header()->num_fds = static_cast<uint16>(num_fds); | 834 msg->header()->num_fds = static_cast<uint16>(num_fds); |
| 841 | 835 |
| 842 #if !defined(OS_MACOSX) | 836 #if defined(IPC_USES_READWRITE) |
| 843 if (!uses_fifo_ && | 837 if (!uses_fifo_ && |
| 844 (msg->routing_id() != MSG_ROUTING_NONE || | 838 (msg->routing_id() != MSG_ROUTING_NONE || |
| 845 msg->type() != HELLO_MESSAGE_TYPE)) { | 839 msg->type() != HELLO_MESSAGE_TYPE)) { |
| 846 // Only the Hello message sends the file descriptor with the message. | 840 // Only the Hello message sends the file descriptor with the message. |
| 847 // Subsequently, we can send file descriptors on the dedicated | 841 // Subsequently, we can send file descriptors on the dedicated |
| 848 // fd_pipe_ which makes Seccomp sandbox operation more efficient. | 842 // fd_pipe_ which makes Seccomp sandbox operation more efficient. |
| 849 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; | 843 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; |
| 850 msgh.msg_iov = &fd_pipe_iov; | 844 msgh.msg_iov = &fd_pipe_iov; |
| 851 fd_written = fd_pipe_; | 845 fd_written = fd_pipe_; |
| 852 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); | 846 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); |
| 853 msgh.msg_iov = &iov; | 847 msgh.msg_iov = &iov; |
| 854 msgh.msg_controllen = 0; | 848 msgh.msg_controllen = 0; |
| 855 if (bytes_written > 0) { | 849 if (bytes_written > 0) { |
| 856 msg->file_descriptor_set()->CommitAll(); | 850 msg->file_descriptor_set()->CommitAll(); |
| 857 } | 851 } |
| 858 } | 852 } |
| 859 #endif | 853 #endif |
| 860 } | 854 } |
| 861 | 855 |
| 862 if (bytes_written == 1) { | 856 if (bytes_written == 1) { |
| 863 fd_written = pipe_; | 857 fd_written = pipe_; |
| 864 #if !defined(OS_MACOSX) | 858 #if defined(IPC_USES_READWRITE) |
| 865 if (mode_ != MODE_SERVER && !uses_fifo_ && | 859 if (mode_ != MODE_SERVER && !uses_fifo_ && |
| 866 msg->routing_id() == MSG_ROUTING_NONE && | 860 msg->routing_id() == MSG_ROUTING_NONE && |
| 867 msg->type() == HELLO_MESSAGE_TYPE) { | 861 msg->type() == HELLO_MESSAGE_TYPE) { |
| 868 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); | 862 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); |
| 869 } | 863 } |
| 870 if (!uses_fifo_ && !msgh.msg_controllen) { | 864 if (!uses_fifo_ && !msgh.msg_controllen) { |
| 871 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); | 865 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); |
| 872 } else | 866 } else |
| 873 #endif | 867 #endif |
| 874 { | 868 { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 write_watcher_.StopWatchingFileDescriptor(); | 1017 write_watcher_.StopWatchingFileDescriptor(); |
| 1024 if (pipe_ != -1) { | 1018 if (pipe_ != -1) { |
| 1025 if (HANDLE_EINTR(close(pipe_)) < 0) | 1019 if (HANDLE_EINTR(close(pipe_)) < 0) |
| 1026 PLOG(ERROR) << "close"; | 1020 PLOG(ERROR) << "close"; |
| 1027 pipe_ = -1; | 1021 pipe_ = -1; |
| 1028 } | 1022 } |
| 1029 if (client_pipe_ != -1) { | 1023 if (client_pipe_ != -1) { |
| 1030 PipeMap::GetInstance()->RemoveAndClose(pipe_name_); | 1024 PipeMap::GetInstance()->RemoveAndClose(pipe_name_); |
| 1031 client_pipe_ = -1; | 1025 client_pipe_ = -1; |
| 1032 } | 1026 } |
| 1033 #if !defined(OS_MACOSX) | 1027 #if defined(IPC_USES_READWRITE) |
| 1034 if (fd_pipe_ != -1) { | 1028 if (fd_pipe_ != -1) { |
| 1035 if (HANDLE_EINTR(close(fd_pipe_)) < 0) | 1029 if (HANDLE_EINTR(close(fd_pipe_)) < 0) |
| 1036 PLOG(ERROR) << "close"; | 1030 PLOG(ERROR) << "close"; |
| 1037 fd_pipe_ = -1; | 1031 fd_pipe_ = -1; |
| 1038 } | 1032 } |
| 1039 if (remote_fd_pipe_ != -1) { | 1033 if (remote_fd_pipe_ != -1) { |
| 1040 if (HANDLE_EINTR(close(remote_fd_pipe_)) < 0) | 1034 if (HANDLE_EINTR(close(remote_fd_pipe_)) < 0) |
| 1041 PLOG(ERROR) << "close"; | 1035 PLOG(ERROR) << "close"; |
| 1042 remote_fd_pipe_ = -1; | 1036 remote_fd_pipe_ = -1; |
| 1043 } | 1037 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1088 | 1082 |
| 1089 bool Channel::Send(Message* message) { | 1083 bool Channel::Send(Message* message) { |
| 1090 return channel_impl_->Send(message); | 1084 return channel_impl_->Send(message); |
| 1091 } | 1085 } |
| 1092 | 1086 |
| 1093 int Channel::GetClientFileDescriptor() const { | 1087 int Channel::GetClientFileDescriptor() const { |
| 1094 return channel_impl_->GetClientFileDescriptor(); | 1088 return channel_impl_->GetClientFileDescriptor(); |
| 1095 } | 1089 } |
| 1096 | 1090 |
| 1097 } // namespace IPC | 1091 } // namespace IPC |
| OLD | NEW |