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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 if (!SocketPair(&local_pipe_fd, &client_pipe_fd)) | 312 if (!SocketPair(&local_pipe_fd, &client_pipe_fd)) |
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 |
hidehiko
2015/05/18 04:54:05
nit: unnecessary empty line?
mdempsky
2015/05/18 17:58:37
Done.
| |
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 | 323 |
350 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { | 324 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { |
351 #if defined(OS_NACL_NONSFI) | 325 #if defined(OS_NACL_NONSFI) |
352 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi " | 326 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi " |
353 << "should not be in NAMED or SERVER mode."; | 327 << "should not be in NAMED or SERVER mode."; |
354 #else | 328 #else |
355 server_listen_pipe_.reset(local_pipe.release()); | 329 server_listen_pipe_.reset(local_pipe.release()); |
356 #endif | 330 #endif |
357 } else { | 331 } else { |
358 pipe_.reset(local_pipe.release()); | 332 pipe_.reset(local_pipe.release()); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 cmsg->cmsg_level = SOL_SOCKET; | 433 cmsg->cmsg_level = SOL_SOCKET; |
460 cmsg->cmsg_type = SCM_RIGHTS; | 434 cmsg->cmsg_type = SCM_RIGHTS; |
461 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | 435 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); |
462 msg->attachment_set()->PeekDescriptors( | 436 msg->attachment_set()->PeekDescriptors( |
463 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | 437 reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
464 msgh.msg_controllen = cmsg->cmsg_len; | 438 msgh.msg_controllen = cmsg->cmsg_len; |
465 | 439 |
466 // DCHECK_LE above already checks that | 440 // DCHECK_LE above already checks that |
467 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. | 441 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. |
468 msg->header()->num_fds = static_cast<uint16>(num_fds); | 442 msg->header()->num_fds = static_cast<uint16>(num_fds); |
469 | 443 |
hidehiko
2015/05/18 04:54:05
nit: unnecessary empty line?
mdempsky
2015/05/18 17:58:36
Done.
| |
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 } | 444 } |
488 | 445 |
489 if (bytes_written == 1) { | 446 if (bytes_written == 1) { |
490 fd_written = pipe_.get(); | 447 fd_written = pipe_.get(); |
491 #if defined(IPC_USES_READWRITE) | |
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 { | 448 { |
hidehiko
2015/05/18 04:54:05
nit: you do not need this brace pair.
mdempsky
2015/05/18 17:58:37
Done.
| |
501 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT)); | 449 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT)); |
502 } | 450 } |
503 } | 451 } |
504 if (bytes_written > 0) | 452 if (bytes_written > 0) |
505 CloseFileDescriptors(msg); | 453 CloseFileDescriptors(msg); |
506 | 454 |
507 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { | 455 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { |
508 // We can't close the pipe here, because calling OnChannelError | 456 // We can't close the pipe here, because calling OnChannelError |
509 // may destroy this object, and that would be bad if we are | 457 // may destroy this object, and that would be bad if we are |
510 // called from Send(). Instead, we return false and hope the | 458 // called from Send(). Instead, we return false and hope the |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
609 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); | 557 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); |
610 return IPC::GetPeerEuid(pipe_.get(), peer_euid); | 558 return IPC::GetPeerEuid(pipe_.get(), peer_euid); |
611 } | 559 } |
612 #endif | 560 #endif |
613 | 561 |
614 void ChannelPosix::ResetToAcceptingConnectionState() { | 562 void ChannelPosix::ResetToAcceptingConnectionState() { |
615 // Unregister libevent for the unix domain socket and close it. | 563 // Unregister libevent for the unix domain socket and close it. |
616 read_watcher_.StopWatchingFileDescriptor(); | 564 read_watcher_.StopWatchingFileDescriptor(); |
617 write_watcher_.StopWatchingFileDescriptor(); | 565 write_watcher_.StopWatchingFileDescriptor(); |
618 ResetSafely(&pipe_); | 566 ResetSafely(&pipe_); |
619 #if defined(IPC_USES_READWRITE) | |
620 fd_pipe_.reset(); | |
621 remote_fd_pipe_.reset(); | |
622 #endif // IPC_USES_READWRITE | |
623 | 567 |
624 while (!output_queue_.empty()) { | 568 while (!output_queue_.empty()) { |
625 Message* m = output_queue_.front(); | 569 Message* m = output_queue_.front(); |
626 output_queue_.pop(); | 570 output_queue_.pop(); |
627 delete m; | 571 delete m; |
628 } | 572 } |
629 | 573 |
630 // Close any outstanding, received file descriptors. | 574 // Close any outstanding, received file descriptors. |
631 ClearInputFDs(); | 575 ClearInputFDs(); |
632 | 576 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
791 } | 735 } |
792 | 736 |
793 void ChannelPosix::QueueHelloMessage() { | 737 void ChannelPosix::QueueHelloMessage() { |
794 // Create the Hello message | 738 // Create the Hello message |
795 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | 739 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, |
796 HELLO_MESSAGE_TYPE, | 740 HELLO_MESSAGE_TYPE, |
797 IPC::Message::PRIORITY_NORMAL)); | 741 IPC::Message::PRIORITY_NORMAL)); |
798 if (!msg->WriteInt(GetHelloMessageProcId())) { | 742 if (!msg->WriteInt(GetHelloMessageProcId())) { |
799 NOTREACHED() << "Unable to pickle hello message proc id"; | 743 NOTREACHED() << "Unable to pickle hello message proc id"; |
800 } | 744 } |
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()); | 745 output_queue_.push(msg.release()); |
812 } | 746 } |
813 | 747 |
814 ChannelPosix::ReadState ChannelPosix::ReadData( | 748 ChannelPosix::ReadState ChannelPosix::ReadData( |
815 char* buffer, | 749 char* buffer, |
816 int buffer_len, | 750 int buffer_len, |
817 int* bytes_read) { | 751 int* bytes_read) { |
818 if (!pipe_.is_valid()) | 752 if (!pipe_.is_valid()) |
819 return READ_FAILED; | 753 return READ_FAILED; |
820 | 754 |
821 struct msghdr msg = {0}; | 755 struct msghdr msg = {0}; |
822 | 756 |
823 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; | 757 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; |
824 msg.msg_iov = &iov; | 758 msg.msg_iov = &iov; |
825 msg.msg_iovlen = 1; | 759 msg.msg_iovlen = 1; |
826 | 760 |
827 msg.msg_control = input_cmsg_buf_; | 761 msg.msg_control = input_cmsg_buf_; |
828 | 762 |
829 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | 763 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data |
830 // is waiting on the pipe. | 764 // is waiting on the pipe. |
831 #if defined(IPC_USES_READWRITE) | |
832 if (fd_pipe_.is_valid()) { | |
833 *bytes_read = HANDLE_EINTR(read(pipe_.get(), buffer, buffer_len)); | |
834 msg.msg_controllen = 0; | |
835 } else | |
836 #endif // IPC_USES_READWRITE | |
837 { | 765 { |
hidehiko
2015/05/18 04:54:05
nit, you do not need this brace pair.
mdempsky
2015/05/18 17:58:36
Done.
| |
838 msg.msg_controllen = sizeof(input_cmsg_buf_); | 766 msg.msg_controllen = sizeof(input_cmsg_buf_); |
839 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT)); | 767 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT)); |
840 } | 768 } |
841 if (*bytes_read < 0) { | 769 if (*bytes_read < 0) { |
842 if (errno == EAGAIN) { | 770 if (errno == EAGAIN) { |
843 return READ_PENDING; | 771 return READ_PENDING; |
844 #if defined(OS_MACOSX) | 772 #if defined(OS_MACOSX) |
845 } else if (errno == EPERM) { | 773 } else if (errno == EPERM) { |
846 // On OSX, reading from a pipe with no listener returns EPERM | 774 // On OSX, reading from a pipe with no listener returns EPERM |
847 // treat this as a special case to prevent spurious error messages | 775 // treat this as a special case to prevent spurious error messages |
(...skipping 13 matching lines...) Expand all Loading... | |
861 DCHECK(*bytes_read); | 789 DCHECK(*bytes_read); |
862 | 790 |
863 CloseClientFileDescriptor(); | 791 CloseClientFileDescriptor(); |
864 | 792 |
865 // Read any file descriptors from the message. | 793 // Read any file descriptors from the message. |
866 if (!ExtractFileDescriptorsFromMsghdr(&msg)) | 794 if (!ExtractFileDescriptorsFromMsghdr(&msg)) |
867 return READ_FAILED; | 795 return READ_FAILED; |
868 return READ_SUCCEEDED; | 796 return READ_SUCCEEDED; |
869 } | 797 } |
870 | 798 |
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 | 799 |
893 // On Posix, we need to fix up the file descriptors before the input message | 800 // On Posix, we need to fix up the file descriptors before the input message |
894 // is dispatched. | 801 // is dispatched. |
895 // | 802 // |
896 // This will read from the input_fds_ (READWRITE mode only) and read more | 803 // This will read from the input_fds_ (READWRITE mode only) and read more |
897 // handles from the FD pipe if necessary. | 804 // handles from the FD pipe if necessary. |
898 bool ChannelPosix::WillDispatchInputMessage(Message* msg) { | 805 bool ChannelPosix::WillDispatchInputMessage(Message* msg) { |
899 uint16 header_fds = msg->header()->num_fds; | 806 uint16 header_fds = msg->header()->num_fds; |
900 if (!header_fds) | 807 if (!header_fds) |
901 return true; // Nothing to do. | 808 return true; // Nothing to do. |
902 | 809 |
903 // The message has file descriptors. | 810 // The message has file descriptors. |
904 const char* error = NULL; | 811 const char* error = NULL; |
905 if (header_fds > input_fds_.size()) { | 812 if (header_fds > input_fds_.size()) { |
906 // The message has been completely received, but we didn't get | 813 // The message has been completely received, but we didn't get |
907 // enough file descriptors. | 814 // enough file descriptors. |
908 #if defined(IPC_USES_READWRITE) | |
909 if (!ReadFileDescriptorsFromFDPipe()) | |
910 return false; | |
911 if (header_fds > input_fds_.size()) | |
912 #endif // IPC_USES_READWRITE | |
913 error = "Message needs unreceived descriptors"; | 815 error = "Message needs unreceived descriptors"; |
hidehiko
2015/05/18 04:54:05
nit: indent?
mdempsky
2015/05/18 17:58:37
Done.
| |
914 } | 816 } |
915 | 817 |
916 if (header_fds > MessageAttachmentSet::kMaxDescriptorsPerMessage) | 818 if (header_fds > MessageAttachmentSet::kMaxDescriptorsPerMessage) |
917 error = "Message requires an excessive number of descriptors"; | 819 error = "Message requires an excessive number of descriptors"; |
918 | 820 |
919 if (error) { | 821 if (error) { |
920 LOG(WARNING) << error | 822 LOG(WARNING) << error |
921 << " channel:" << this | 823 << " channel:" << this |
922 << " message-type:" << msg->type() | 824 << " message-type:" << msg->type() |
923 << " header()->num_fds:" << header_fds; | 825 << " header()->num_fds:" << header_fds; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1010 switch (msg.type()) { | 912 switch (msg.type()) { |
1011 default: | 913 default: |
1012 NOTREACHED(); | 914 NOTREACHED(); |
1013 break; | 915 break; |
1014 | 916 |
1015 case Channel::HELLO_MESSAGE_TYPE: | 917 case Channel::HELLO_MESSAGE_TYPE: |
1016 int pid; | 918 int pid; |
1017 if (!iter.ReadInt(&pid)) | 919 if (!iter.ReadInt(&pid)) |
1018 NOTREACHED(); | 920 NOTREACHED(); |
1019 | 921 |
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; | 922 peer_pid_ = pid; |
1034 listener()->OnChannelConnected(pid); | 923 listener()->OnChannelConnected(pid); |
1035 break; | 924 break; |
1036 | 925 |
1037 #if defined(OS_MACOSX) | 926 #if defined(OS_MACOSX) |
1038 case Channel::CLOSE_FD_MESSAGE_TYPE: | 927 case Channel::CLOSE_FD_MESSAGE_TYPE: |
1039 int fd, hops; | 928 int fd, hops; |
1040 if (!iter.ReadInt(&hops)) | 929 if (!iter.ReadInt(&hops)) |
1041 NOTREACHED(); | 930 NOTREACHED(); |
1042 if (!iter.ReadInt(&fd)) | 931 if (!iter.ReadInt(&fd)) |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1136 } | 1025 } |
1137 | 1026 |
1138 #if defined(OS_LINUX) | 1027 #if defined(OS_LINUX) |
1139 // static | 1028 // static |
1140 void Channel::SetGlobalPid(int pid) { | 1029 void Channel::SetGlobalPid(int pid) { |
1141 ChannelPosix::SetGlobalPid(pid); | 1030 ChannelPosix::SetGlobalPid(pid); |
1142 } | 1031 } |
1143 #endif // OS_LINUX | 1032 #endif // OS_LINUX |
1144 | 1033 |
1145 } // namespace IPC | 1034 } // namespace IPC |
OLD | NEW |