OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/socket.h> | 10 #include <sys/socket.h> |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 // 3) It's for a client that we implement ourself. This is used | 240 // 3) It's for a client that we implement ourself. This is used |
241 // in single-process unittesting. | 241 // in single-process unittesting. |
242 // 4) It's the initial IPC channel: | 242 // 4) It's the initial IPC channel: |
243 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. | 243 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. |
244 // 4b) Server side: create the pipe. | 244 // 4b) Server side: create the pipe. |
245 | 245 |
246 base::ScopedFD local_pipe; | 246 base::ScopedFD local_pipe; |
247 if (channel_handle.socket.fd != -1) { | 247 if (channel_handle.socket.fd != -1) { |
248 // Case 1 from comment above. | 248 // Case 1 from comment above. |
249 local_pipe.reset(channel_handle.socket.fd); | 249 local_pipe.reset(channel_handle.socket.fd); |
250 #if defined(IPC_USES_READWRITE) | |
251 // Test the socket passed into us to make sure it is nonblocking. | |
252 // We don't want to call read/write on a blocking socket. | |
253 int value = fcntl(local_pipe.get(), F_GETFL); | |
254 if (value == -1) { | |
255 PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_; | |
256 return false; | |
257 } | |
258 if (!(value & O_NONBLOCK)) { | |
259 LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK"; | |
260 return false; | |
261 } | |
262 #endif // IPC_USES_READWRITE | |
263 } else if (mode_ & MODE_NAMED_FLAG) { | 250 } else if (mode_ & MODE_NAMED_FLAG) { |
264 #if defined(OS_NACL_NONSFI) | 251 #if defined(OS_NACL_NONSFI) |
265 LOG(FATAL) | 252 LOG(FATAL) |
266 << "IPC channels in nacl_helper_nonsfi should not be in NAMED mode."; | 253 << "IPC channels in nacl_helper_nonsfi should not be in NAMED mode."; |
267 #else | 254 #else |
268 // Case 2 from comment above. | 255 // Case 2 from comment above. |
269 int local_pipe_fd = -1; | 256 int local_pipe_fd = -1; |
270 | 257 |
271 if (mode_ & MODE_SERVER_FLAG) { | 258 if (mode_ & MODE_SERVER_FLAG) { |
272 if (!CreateServerUnixDomainSocket(base::FilePath(pipe_name_), | 259 if (!CreateServerUnixDomainSocket(base::FilePath(pipe_name_), |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 return false; | 313 return false; |
327 local_pipe.reset(local_pipe_fd); | 314 local_pipe.reset(local_pipe_fd); |
328 client_pipe_.reset(client_pipe_fd); | 315 client_pipe_.reset(client_pipe_fd); |
329 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_fd); | 316 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_fd); |
330 } else { | 317 } else { |
331 LOG(ERROR) << "Bad mode: " << mode_; | 318 LOG(ERROR) << "Bad mode: " << mode_; |
332 return false; | 319 return false; |
333 } | 320 } |
334 } | 321 } |
335 | 322 |
336 #if defined(IPC_USES_READWRITE) | |
337 // Create a dedicated socketpair() for exchanging file descriptors. | |
338 // See comments for IPC_USES_READWRITE for details. | |
339 if (mode_ & MODE_CLIENT_FLAG) { | |
340 int fd_pipe_fd = 1, remote_fd_pipe_fd = -1; | |
341 if (!SocketPair(&fd_pipe_fd, &remote_fd_pipe_fd)) { | |
342 return false; | |
343 } | |
344 | |
345 fd_pipe_.reset(fd_pipe_fd); | |
346 remote_fd_pipe_.reset(remote_fd_pipe_fd); | |
347 } | |
348 #endif // IPC_USES_READWRITE | |
349 | |
350 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { | 323 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { |
351 #if defined(OS_NACL_NONSFI) | 324 #if defined(OS_NACL_NONSFI) |
352 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi " | 325 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi " |
353 << "should not be in NAMED or SERVER mode."; | 326 << "should not be in NAMED or SERVER mode."; |
354 #else | 327 #else |
355 server_listen_pipe_.reset(local_pipe.release()); | 328 server_listen_pipe_.reset(local_pipe.release()); |
356 #endif | 329 #endif |
357 } else { | 330 } else { |
358 pipe_.reset(local_pipe.release()); | 331 pipe_.reset(local_pipe.release()); |
359 } | 332 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 cmsg->cmsg_level = SOL_SOCKET; | 432 cmsg->cmsg_level = SOL_SOCKET; |
460 cmsg->cmsg_type = SCM_RIGHTS; | 433 cmsg->cmsg_type = SCM_RIGHTS; |
461 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | 434 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); |
462 msg->attachment_set()->PeekDescriptors( | 435 msg->attachment_set()->PeekDescriptors( |
463 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | 436 reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
464 msgh.msg_controllen = cmsg->cmsg_len; | 437 msgh.msg_controllen = cmsg->cmsg_len; |
465 | 438 |
466 // DCHECK_LE above already checks that | 439 // DCHECK_LE above already checks that |
467 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. | 440 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. |
468 msg->header()->num_fds = static_cast<uint16>(num_fds); | 441 msg->header()->num_fds = static_cast<uint16>(num_fds); |
469 | |
470 #if defined(IPC_USES_READWRITE) | |
471 if (!IsHelloMessage(*msg)) { | |
472 // Only the Hello message sends the file descriptor with the message. | |
473 // Subsequently, we can send file descriptors on the dedicated | |
474 // fd_pipe_ which makes Seccomp sandbox operation more efficient. | |
475 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; | |
476 msgh.msg_iov = &fd_pipe_iov; | |
477 fd_written = fd_pipe_.get(); | |
478 bytes_written = | |
479 HANDLE_EINTR(sendmsg(fd_pipe_.get(), &msgh, MSG_DONTWAIT)); | |
480 msgh.msg_iov = &iov; | |
481 msgh.msg_controllen = 0; | |
482 if (bytes_written > 0) { | |
483 CloseFileDescriptors(msg); | |
484 } | |
485 } | |
486 #endif // IPC_USES_READWRITE | |
487 } | 442 } |
488 | 443 |
489 if (bytes_written == 1) { | 444 if (bytes_written == 1) { |
490 fd_written = pipe_.get(); | 445 fd_written = pipe_.get(); |
491 #if defined(IPC_USES_READWRITE) | 446 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT)); |
492 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) { | |
493 DCHECK_EQ(msg->attachment_set()->size(), 1U); | |
494 } | |
495 if (!msgh.msg_controllen) { | |
496 bytes_written = | |
497 HANDLE_EINTR(write(pipe_.get(), out_bytes, amt_to_write)); | |
498 } else | |
499 #endif // IPC_USES_READWRITE | |
500 { | |
501 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT)); | |
502 } | |
503 } | 447 } |
504 if (bytes_written > 0) | 448 if (bytes_written > 0) |
505 CloseFileDescriptors(msg); | 449 CloseFileDescriptors(msg); |
506 | 450 |
507 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { | 451 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { |
508 // We can't close the pipe here, because calling OnChannelError | 452 // We can't close the pipe here, because calling OnChannelError |
509 // may destroy this object, and that would be bad if we are | 453 // may destroy this object, and that would be bad if we are |
510 // called from Send(). Instead, we return false and hope the | 454 // called from Send(). Instead, we return false and hope the |
511 // caller will close the pipe. If they do not, the pipe will | 455 // caller will close the pipe. If they do not, the pipe will |
512 // still be closed next time OnFileCanReadWithoutBlocking is | 456 // still be closed next time OnFileCanReadWithoutBlocking is |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); | 553 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); |
610 return IPC::GetPeerEuid(pipe_.get(), peer_euid); | 554 return IPC::GetPeerEuid(pipe_.get(), peer_euid); |
611 } | 555 } |
612 #endif | 556 #endif |
613 | 557 |
614 void ChannelPosix::ResetToAcceptingConnectionState() { | 558 void ChannelPosix::ResetToAcceptingConnectionState() { |
615 // Unregister libevent for the unix domain socket and close it. | 559 // Unregister libevent for the unix domain socket and close it. |
616 read_watcher_.StopWatchingFileDescriptor(); | 560 read_watcher_.StopWatchingFileDescriptor(); |
617 write_watcher_.StopWatchingFileDescriptor(); | 561 write_watcher_.StopWatchingFileDescriptor(); |
618 ResetSafely(&pipe_); | 562 ResetSafely(&pipe_); |
619 #if defined(IPC_USES_READWRITE) | |
620 fd_pipe_.reset(); | |
621 remote_fd_pipe_.reset(); | |
622 #endif // IPC_USES_READWRITE | |
623 | 563 |
624 while (!output_queue_.empty()) { | 564 while (!output_queue_.empty()) { |
625 Message* m = output_queue_.front(); | 565 Message* m = output_queue_.front(); |
626 output_queue_.pop(); | 566 output_queue_.pop(); |
627 delete m; | 567 delete m; |
628 } | 568 } |
629 | 569 |
630 // Close any outstanding, received file descriptors. | 570 // Close any outstanding, received file descriptors. |
631 ClearInputFDs(); | 571 ClearInputFDs(); |
632 | 572 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
791 } | 731 } |
792 | 732 |
793 void ChannelPosix::QueueHelloMessage() { | 733 void ChannelPosix::QueueHelloMessage() { |
794 // Create the Hello message | 734 // Create the Hello message |
795 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | 735 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, |
796 HELLO_MESSAGE_TYPE, | 736 HELLO_MESSAGE_TYPE, |
797 IPC::Message::PRIORITY_NORMAL)); | 737 IPC::Message::PRIORITY_NORMAL)); |
798 if (!msg->WriteInt(GetHelloMessageProcId())) { | 738 if (!msg->WriteInt(GetHelloMessageProcId())) { |
799 NOTREACHED() << "Unable to pickle hello message proc id"; | 739 NOTREACHED() << "Unable to pickle hello message proc id"; |
800 } | 740 } |
801 #if defined(IPC_USES_READWRITE) | |
802 scoped_ptr<Message> hello; | |
803 if (remote_fd_pipe_.is_valid()) { | |
804 if (!msg->WriteAttachment( | |
805 new internal::PlatformFileAttachment(remote_fd_pipe_.get()))) { | |
806 NOTREACHED() << "Unable to pickle hello message file descriptors"; | |
807 } | |
808 DCHECK_EQ(msg->attachment_set()->size(), 1U); | |
809 } | |
810 #endif // IPC_USES_READWRITE | |
811 output_queue_.push(msg.release()); | 741 output_queue_.push(msg.release()); |
812 } | 742 } |
813 | 743 |
814 ChannelPosix::ReadState ChannelPosix::ReadData( | 744 ChannelPosix::ReadState ChannelPosix::ReadData( |
815 char* buffer, | 745 char* buffer, |
816 int buffer_len, | 746 int buffer_len, |
817 int* bytes_read) { | 747 int* bytes_read) { |
818 if (!pipe_.is_valid()) | 748 if (!pipe_.is_valid()) |
819 return READ_FAILED; | 749 return READ_FAILED; |
820 | 750 |
821 struct msghdr msg = {0}; | 751 struct msghdr msg = {0}; |
822 | 752 |
823 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; | 753 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; |
824 msg.msg_iov = &iov; | 754 msg.msg_iov = &iov; |
825 msg.msg_iovlen = 1; | 755 msg.msg_iovlen = 1; |
826 | 756 |
827 msg.msg_control = input_cmsg_buf_; | 757 msg.msg_control = input_cmsg_buf_; |
828 | 758 |
829 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | 759 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data |
830 // is waiting on the pipe. | 760 // is waiting on the pipe. |
831 #if defined(IPC_USES_READWRITE) | 761 msg.msg_controllen = sizeof(input_cmsg_buf_); |
832 if (fd_pipe_.is_valid()) { | 762 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT)); |
833 *bytes_read = HANDLE_EINTR(read(pipe_.get(), buffer, buffer_len)); | 763 |
834 msg.msg_controllen = 0; | |
835 } else | |
836 #endif // IPC_USES_READWRITE | |
837 { | |
838 msg.msg_controllen = sizeof(input_cmsg_buf_); | |
839 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT)); | |
840 } | |
841 if (*bytes_read < 0) { | 764 if (*bytes_read < 0) { |
842 if (errno == EAGAIN) { | 765 if (errno == EAGAIN) { |
843 return READ_PENDING; | 766 return READ_PENDING; |
844 #if defined(OS_MACOSX) | 767 #if defined(OS_MACOSX) |
845 } else if (errno == EPERM) { | 768 } else if (errno == EPERM) { |
846 // On OSX, reading from a pipe with no listener returns EPERM | 769 // On OSX, reading from a pipe with no listener returns EPERM |
847 // treat this as a special case to prevent spurious error messages | 770 // treat this as a special case to prevent spurious error messages |
848 // to the console. | 771 // to the console. |
849 return READ_FAILED; | 772 return READ_FAILED; |
850 #endif // OS_MACOSX | 773 #endif // OS_MACOSX |
(...skipping 10 matching lines...) Expand all Loading... |
861 DCHECK(*bytes_read); | 784 DCHECK(*bytes_read); |
862 | 785 |
863 CloseClientFileDescriptor(); | 786 CloseClientFileDescriptor(); |
864 | 787 |
865 // Read any file descriptors from the message. | 788 // Read any file descriptors from the message. |
866 if (!ExtractFileDescriptorsFromMsghdr(&msg)) | 789 if (!ExtractFileDescriptorsFromMsghdr(&msg)) |
867 return READ_FAILED; | 790 return READ_FAILED; |
868 return READ_SUCCEEDED; | 791 return READ_SUCCEEDED; |
869 } | 792 } |
870 | 793 |
871 #if defined(IPC_USES_READWRITE) | |
872 bool ChannelPosix::ReadFileDescriptorsFromFDPipe() { | |
873 char dummy; | |
874 struct iovec fd_pipe_iov = { &dummy, 1 }; | |
875 | |
876 struct msghdr msg = { 0 }; | |
877 msg.msg_iov = &fd_pipe_iov; | |
878 msg.msg_iovlen = 1; | |
879 msg.msg_control = input_cmsg_buf_; | |
880 msg.msg_controllen = sizeof(input_cmsg_buf_); | |
881 ssize_t bytes_received = | |
882 HANDLE_EINTR(recvmsg(fd_pipe_.get(), &msg, MSG_DONTWAIT)); | |
883 | |
884 if (bytes_received != 1) | |
885 return true; // No message waiting. | |
886 | |
887 if (!ExtractFileDescriptorsFromMsghdr(&msg)) | |
888 return false; | |
889 return true; | |
890 } | |
891 #endif | |
892 | |
893 // On Posix, we need to fix up the file descriptors before the input message | 794 // On Posix, we need to fix up the file descriptors before the input message |
894 // is dispatched. | 795 // is dispatched. |
895 // | 796 // |
896 // This will read from the input_fds_ (READWRITE mode only) and read more | 797 // This will read from the input_fds_ (READWRITE mode only) and read more |
897 // handles from the FD pipe if necessary. | 798 // handles from the FD pipe if necessary. |
898 bool ChannelPosix::WillDispatchInputMessage(Message* msg) { | 799 bool ChannelPosix::WillDispatchInputMessage(Message* msg) { |
899 uint16 header_fds = msg->header()->num_fds; | 800 uint16 header_fds = msg->header()->num_fds; |
900 if (!header_fds) | 801 if (!header_fds) |
901 return true; // Nothing to do. | 802 return true; // Nothing to do. |
902 | 803 |
903 // The message has file descriptors. | 804 // The message has file descriptors. |
904 const char* error = NULL; | 805 const char* error = NULL; |
905 if (header_fds > input_fds_.size()) { | 806 if (header_fds > input_fds_.size()) { |
906 // The message has been completely received, but we didn't get | 807 // The message has been completely received, but we didn't get |
907 // enough file descriptors. | 808 // enough file descriptors. |
908 #if defined(IPC_USES_READWRITE) | 809 error = "Message needs unreceived descriptors"; |
909 if (!ReadFileDescriptorsFromFDPipe()) | |
910 return false; | |
911 if (header_fds > input_fds_.size()) | |
912 #endif // IPC_USES_READWRITE | |
913 error = "Message needs unreceived descriptors"; | |
914 } | 810 } |
915 | 811 |
916 if (header_fds > MessageAttachmentSet::kMaxDescriptorsPerMessage) | 812 if (header_fds > MessageAttachmentSet::kMaxDescriptorsPerMessage) |
917 error = "Message requires an excessive number of descriptors"; | 813 error = "Message requires an excessive number of descriptors"; |
918 | 814 |
919 if (error) { | 815 if (error) { |
920 LOG(WARNING) << error | 816 LOG(WARNING) << error |
921 << " channel:" << this | 817 << " channel:" << this |
922 << " message-type:" << msg->type() | 818 << " message-type:" << msg->type() |
923 << " header()->num_fds:" << header_fds; | 819 << " header()->num_fds:" << header_fds; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1010 switch (msg.type()) { | 906 switch (msg.type()) { |
1011 default: | 907 default: |
1012 NOTREACHED(); | 908 NOTREACHED(); |
1013 break; | 909 break; |
1014 | 910 |
1015 case Channel::HELLO_MESSAGE_TYPE: | 911 case Channel::HELLO_MESSAGE_TYPE: |
1016 int pid; | 912 int pid; |
1017 if (!iter.ReadInt(&pid)) | 913 if (!iter.ReadInt(&pid)) |
1018 NOTREACHED(); | 914 NOTREACHED(); |
1019 | 915 |
1020 #if defined(IPC_USES_READWRITE) | |
1021 if (mode_ & MODE_SERVER_FLAG) { | |
1022 // With IPC_USES_READWRITE, the Hello message from the client to the | |
1023 // server also contains the fd_pipe_, which will be used for all | |
1024 // subsequent file descriptor passing. | |
1025 DCHECK_EQ(msg.attachment_set()->size(), 1U); | |
1026 scoped_refptr<MessageAttachment> attachment; | |
1027 if (!msg.ReadAttachment(&iter, &attachment)) { | |
1028 NOTREACHED(); | |
1029 } | |
1030 fd_pipe_.reset(attachment->TakePlatformFile()); | |
1031 } | |
1032 #endif // IPC_USES_READWRITE | |
1033 peer_pid_ = pid; | 916 peer_pid_ = pid; |
1034 listener()->OnChannelConnected(pid); | 917 listener()->OnChannelConnected(pid); |
1035 break; | 918 break; |
1036 | 919 |
1037 #if defined(OS_MACOSX) | 920 #if defined(OS_MACOSX) |
1038 case Channel::CLOSE_FD_MESSAGE_TYPE: | 921 case Channel::CLOSE_FD_MESSAGE_TYPE: |
1039 int fd, hops; | 922 int fd, hops; |
1040 if (!iter.ReadInt(&hops)) | 923 if (!iter.ReadInt(&hops)) |
1041 NOTREACHED(); | 924 NOTREACHED(); |
1042 if (!iter.ReadInt(&fd)) | 925 if (!iter.ReadInt(&fd)) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 // A random name is sufficient validation on posix systems, so we don't need | 1005 // A random name is sufficient validation on posix systems, so we don't need |
1123 // an additional shared secret. | 1006 // an additional shared secret. |
1124 | 1007 |
1125 std::string id = prefix; | 1008 std::string id = prefix; |
1126 if (!id.empty()) | 1009 if (!id.empty()) |
1127 id.append("."); | 1010 id.append("."); |
1128 | 1011 |
1129 return id.append(GenerateUniqueRandomChannelID()); | 1012 return id.append(GenerateUniqueRandomChannelID()); |
1130 } | 1013 } |
1131 | 1014 |
1132 | |
1133 bool Channel::IsNamedServerInitialized( | 1015 bool Channel::IsNamedServerInitialized( |
1134 const std::string& channel_id) { | 1016 const std::string& channel_id) { |
1135 return ChannelPosix::IsNamedServerInitialized(channel_id); | 1017 return ChannelPosix::IsNamedServerInitialized(channel_id); |
1136 } | 1018 } |
1137 | 1019 |
1138 #if defined(OS_LINUX) | 1020 #if defined(OS_LINUX) |
1139 // static | 1021 // static |
1140 void Channel::SetGlobalPid(int pid) { | 1022 void Channel::SetGlobalPid(int pid) { |
1141 ChannelPosix::SetGlobalPid(pid); | 1023 ChannelPosix::SetGlobalPid(pid); |
1142 } | 1024 } |
1143 #endif // OS_LINUX | 1025 #endif // OS_LINUX |
1144 | 1026 |
1145 } // namespace IPC | 1027 } // namespace IPC |
OLD | NEW |