Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: ipc/ipc_channel_posix.cc

Issue 1139703005: ipc: remove IPC_USES_READWRITE (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Nits from hidehiko@ Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698