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 |