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

Side by Side Diff: ipc/ipc_channel_posix.cc

Issue 9533002: Clean up in ipc_channel_posix. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 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 | Annotate | Revision Log
« 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/types.h> 10 #include <sys/types.h>
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 MessageLoopForIO::WATCH_READ, 472 MessageLoopForIO::WATCH_READ,
473 &server_listen_connection_watcher_, 473 &server_listen_connection_watcher_,
474 this); 474 this);
475 } else { 475 } else {
476 did_connect = AcceptConnection(); 476 did_connect = AcceptConnection();
477 } 477 }
478 return did_connect; 478 return did_connect;
479 } 479 }
480 480
481 bool Channel::ChannelImpl::ProcessIncomingMessages() { 481 bool Channel::ChannelImpl::ProcessIncomingMessages() {
482 ssize_t bytes_read = 0; 482 for (;;) {
483 if (pipe_ == -1)
484 return false;
483 485
484 struct msghdr msg = {0}; 486 const char* p = NULL;
485 struct iovec iov = {input_buf_, Channel::kReadBufferSize}; 487 const char* end = NULL;
488 if (!ReadDataFromPipe(&p, &end))
489 return false; // Pipe error.
490 if (!p)
491 return true; // No data waiting.
486 492
487 msg.msg_iovlen = 1; 493 // Dispatch all complete messages in the data buffer.
488 msg.msg_control = input_cmsg_buf_;
489
490 for (;;) {
491 msg.msg_iov = &iov;
492
493 if (bytes_read == 0) {
494 if (pipe_ == -1)
495 return false;
496
497 // Read from pipe.
498 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data
499 // is waiting on the pipe.
500 #if defined(IPC_USES_READWRITE)
501 if (fd_pipe_ >= 0) {
502 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_,
503 Channel::kReadBufferSize));
504 msg.msg_controllen = 0;
505 } else
506 #endif // IPC_USES_READWRITE
507 {
508 msg.msg_controllen = sizeof(input_cmsg_buf_);
509 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
510 }
511 if (bytes_read < 0) {
512 if (errno == EAGAIN) {
513 return true;
514 #if defined(OS_MACOSX)
515 } else if (errno == EPERM) {
516 // On OSX, reading from a pipe with no listener returns EPERM
517 // treat this as a special case to prevent spurious error messages
518 // to the console.
519 return false;
520 #endif // OS_MACOSX
521 } else if (errno == ECONNRESET || errno == EPIPE) {
522 return false;
523 } else {
524 PLOG(ERROR) << "pipe error (" << pipe_ << ")";
525 return false;
526 }
527 } else if (bytes_read == 0) {
528 // The pipe has closed...
529 return false;
530 }
531 }
532 DCHECK(bytes_read);
533
534 CloseClientFileDescriptor();
535
536 // a pointer to an array of |num_wire_fds| file descriptors from the read
537 const int* wire_fds = NULL;
538 unsigned num_wire_fds = 0;
539
540 // walk the list of control messages and, if we find an array of file
541 // descriptors, save a pointer to the array
542
543 // This next if statement is to work around an OSX issue where
544 // CMSG_FIRSTHDR will return non-NULL in the case that controllen == 0.
545 // Here's a test case:
546 //
547 // int main() {
548 // struct msghdr msg;
549 // msg.msg_control = &msg;
550 // msg.msg_controllen = 0;
551 // if (CMSG_FIRSTHDR(&msg))
552 // printf("Bug found!\n");
553 // }
554 if (msg.msg_controllen > 0) {
555 // On OSX, CMSG_FIRSTHDR doesn't handle the case where controllen is 0
556 // and will return a pointer into nowhere.
557 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
558 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
559 if (cmsg->cmsg_level == SOL_SOCKET &&
560 cmsg->cmsg_type == SCM_RIGHTS) {
561 const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
562 DCHECK_EQ(0U, payload_len % sizeof(int));
563 wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
564 num_wire_fds = payload_len / 4;
565
566 if (msg.msg_flags & MSG_CTRUNC) {
567 LOG(ERROR) << "SCM_RIGHTS message was truncated"
568 << " cmsg_len:" << cmsg->cmsg_len
569 << " fd:" << pipe_;
570 for (unsigned i = 0; i < num_wire_fds; ++i)
571 if (HANDLE_EINTR(close(wire_fds[i])) < 0)
572 PLOG(ERROR) << "close " << i;
573 return false;
574 }
575 break;
576 }
577 }
578 }
579
580 // Process messages from input buffer.
581 const char *p;
582 const char *end;
583 if (input_overflow_buf_.empty()) {
584 p = input_buf_;
585 end = p + bytes_read;
586 } else {
587 if (input_overflow_buf_.size() > (kMaximumMessageSize - bytes_read)) {
588 input_overflow_buf_.clear();
589 LOG(ERROR) << "IPC message is too big";
590 return false;
591 }
592 input_overflow_buf_.append(input_buf_, bytes_read);
593 p = input_overflow_buf_.data();
594 end = p + input_overflow_buf_.size();
595 }
596
597 // A pointer to an array of |num_fds| file descriptors which includes any
598 // fds that have spilled over from a previous read.
599 const int* fds = NULL;
600 unsigned num_fds = 0;
601 unsigned fds_i = 0; // the index of the first unused descriptor
602
603 if (input_overflow_fds_.empty()) {
604 fds = wire_fds;
605 num_fds = num_wire_fds;
606 } else {
607 if (num_wire_fds > 0) {
608 const size_t prev_size = input_overflow_fds_.size();
609 input_overflow_fds_.resize(prev_size + num_wire_fds);
610 memcpy(&input_overflow_fds_[prev_size], wire_fds,
611 num_wire_fds * sizeof(int));
612 }
613 fds = &input_overflow_fds_[0];
614 num_fds = input_overflow_fds_.size();
615 }
616
617 while (p < end) { 494 while (p < end) {
618 const char* message_tail = Message::FindNext(p, end); 495 const char* message_tail = Message::FindNext(p, end);
619 if (message_tail) { 496 if (message_tail) {
620 int len = static_cast<int>(message_tail - p); 497 int len = static_cast<int>(message_tail - p);
621 Message m(p, len); 498 Message m(p, len);
622 const uint16 header_fds = m.header()->num_fds; 499 if (!PopulateMessageFileDescriptors(&m))
623 if (header_fds) { 500 return false;
624 // the message has file descriptors
625 const char* error = NULL;
626 if (header_fds > num_fds - fds_i) {
627 // the message has been completely received, but we didn't get
628 // enough file descriptors.
629 #if defined(IPC_USES_READWRITE)
630 char dummy;
631 struct iovec fd_pipe_iov = { &dummy, 1 };
632 msg.msg_iov = &fd_pipe_iov;
633 msg.msg_controllen = sizeof(input_cmsg_buf_);
634 ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT));
635 if (n == 1 && msg.msg_controllen > 0) {
636 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
637 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
638 if (cmsg->cmsg_level == SOL_SOCKET &&
639 cmsg->cmsg_type == SCM_RIGHTS) {
640 const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
641 DCHECK_EQ(0U, payload_len % sizeof(int));
642 wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
643 num_wire_fds = payload_len / 4;
644 501
645 if (msg.msg_flags & MSG_CTRUNC) {
646 LOG(ERROR) << "SCM_RIGHTS message was truncated"
647 << " cmsg_len:" << cmsg->cmsg_len
648 << " fd:" << pipe_;
649 for (unsigned i = 0; i < num_wire_fds; ++i)
650 if (HANDLE_EINTR(close(wire_fds[i])) < 0)
651 PLOG(ERROR) << "close " << i;
652 return false;
653 }
654 break;
655 }
656 }
657 if (input_overflow_fds_.empty()) {
658 fds = wire_fds;
659 num_fds = num_wire_fds;
660 } else {
661 if (num_wire_fds > 0) {
662 const size_t prev_size = input_overflow_fds_.size();
663 input_overflow_fds_.resize(prev_size + num_wire_fds);
664 memcpy(&input_overflow_fds_[prev_size], wire_fds,
665 num_wire_fds * sizeof(int));
666 }
667 fds = &input_overflow_fds_[0];
668 num_fds = input_overflow_fds_.size();
669 }
670 }
671 if (header_fds > num_fds - fds_i)
672 #endif // IPC_USES_READWRITE
673 error = "Message needs unreceived descriptors";
674 }
675
676 if (header_fds >
677 FileDescriptorSet::kMaxDescriptorsPerMessage) {
678 // There are too many descriptors in this message
679 error = "Message requires an excessive number of descriptors";
680 }
681
682 if (error) {
683 LOG(WARNING) << error
684 << " channel:" << this
685 << " message-type:" << m.type()
686 << " header()->num_fds:" << header_fds
687 << " num_fds:" << num_fds
688 << " fds_i:" << fds_i;
689 #if defined(CHROMIUM_SELINUX)
690 LOG(WARNING) << "In the case of SELinux this can be caused when "
691 "using a --user-data-dir to which the default "
692 "policy doesn't give the renderer access to. ";
693 #endif // CHROMIUM_SELINUX
694 // close the existing file descriptors so that we don't leak them
695 for (unsigned i = fds_i; i < num_fds; ++i)
696 if (HANDLE_EINTR(close(fds[i])) < 0)
697 PLOG(ERROR) << "close " << i;
698 input_overflow_fds_.clear();
699 // abort the connection
700 return false;
701 }
702
703 m.file_descriptor_set()->SetDescriptors(
704 &fds[fds_i], header_fds);
705 fds_i += header_fds;
706 }
707 DVLOG(2) << "received message on channel @" << this 502 DVLOG(2) << "received message on channel @" << this
708 << " with type " << m.type() << " on fd " << pipe_; 503 << " with type " << m.type() << " on fd " << pipe_;
709 if (IsHelloMessage(&m)) { 504 if (IsHelloMessage(&m))
710 // The Hello message contains only the process id. 505 HandleHelloMessage(m);
711 void *iter = NULL; 506 else
712 int pid;
713 if (!m.ReadInt(&iter, &pid)) {
714 NOTREACHED();
715 }
716 #if defined(IPC_USES_READWRITE)
717 if (mode_ & MODE_SERVER_FLAG) {
718 // With IPC_USES_READWRITE, the Hello message from the client to the
719 // server also contains the fd_pipe_, which will be used for all
720 // subsequent file descriptor passing.
721 DCHECK_EQ(m.file_descriptor_set()->size(), 1U);
722 base::FileDescriptor descriptor;
723 if (!m.ReadFileDescriptor(&iter, &descriptor)) {
724 NOTREACHED();
725 }
726 fd_pipe_ = descriptor.fd;
727 CHECK(descriptor.auto_close);
728 }
729 #endif // IPC_USES_READWRITE
730 listener_->OnChannelConnected(pid);
731 } else {
732 listener_->OnMessageReceived(m); 507 listener_->OnMessageReceived(m);
733 }
734 p = message_tail; 508 p = message_tail;
735 } else { 509 } else {
736 // Last message is partial. 510 // Last message is partial.
737 break; 511 break;
738 } 512 }
739 input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]);
740 fds_i = 0;
741 fds = vector_as_array(&input_overflow_fds_);
742 num_fds = input_overflow_fds_.size();
743 } 513 }
744 input_overflow_buf_.assign(p, end - p); 514 input_overflow_buf_.assign(p, end - p);
745 input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]);
746 515
747 // When the input data buffer is empty, the overflow fds should be too. If 516 // When the input data buffer is empty, the fds should be too. If this is
748 // this is not the case, we probably have a rogue renderer which is trying 517 // not the case, we probably have a rogue renderer which is trying to fill
749 // to fill our descriptor table. 518 // our descriptor table.
750 if (input_overflow_buf_.empty() && !input_overflow_fds_.empty()) { 519 if (input_overflow_buf_.empty() && !input_fds_.empty()) {
751 // We close these descriptors in Close() 520 // We close these descriptors in Close()
752 return false; 521 return false;
753 } 522 }
754
755 bytes_read = 0; // Get more data.
756 } 523 }
757 } 524 }
758 525
759 bool Channel::ChannelImpl::ProcessOutgoingMessages() { 526 bool Channel::ChannelImpl::ProcessOutgoingMessages() {
760 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 527 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
761 // no connection? 528 // no connection?
762 if (output_queue_.empty()) 529 if (output_queue_.empty())
763 return true; 530 return true;
764 531
765 if (pipe_ == -1) 532 if (pipe_ == -1)
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 } 766 }
1000 #endif // IPC_USES_READWRITE 767 #endif // IPC_USES_READWRITE
1001 768
1002 while (!output_queue_.empty()) { 769 while (!output_queue_.empty()) {
1003 Message* m = output_queue_.front(); 770 Message* m = output_queue_.front();
1004 output_queue_.pop(); 771 output_queue_.pop();
1005 delete m; 772 delete m;
1006 } 773 }
1007 774
1008 // Close any outstanding, received file descriptors. 775 // Close any outstanding, received file descriptors.
1009 for (std::vector<int>::iterator 776 ClearInputFDs();
1010 i = input_overflow_fds_.begin(); i != input_overflow_fds_.end(); ++i) {
1011 if (HANDLE_EINTR(close(*i)) < 0)
1012 PLOG(ERROR) << "close";
1013 }
1014 input_overflow_fds_.clear();
1015 } 777 }
1016 778
1017 // static 779 // static
1018 bool Channel::ChannelImpl::IsNamedServerInitialized( 780 bool Channel::ChannelImpl::IsNamedServerInitialized(
1019 const std::string& channel_id) { 781 const std::string& channel_id) {
1020 return file_util::PathExists(FilePath(channel_id)); 782 return file_util::PathExists(FilePath(channel_id));
1021 } 783 }
1022 784
1023 #if defined(OS_LINUX) 785 #if defined(OS_LINUX)
1024 // static 786 // static
1025 void Channel::ChannelImpl::SetGlobalPid(int pid) { 787 void Channel::ChannelImpl::SetGlobalPid(int pid) {
1026 global_pid_ = pid; 788 global_pid_ = pid;
1027 } 789 }
1028 #endif // OS_LINUX 790 #endif // OS_LINUX
1029 791
1030 // Called by libevent when we can read from the pipe without blocking. 792 // Called by libevent when we can read from the pipe without blocking.
1031 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { 793 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) {
1032 bool send_server_hello_msg = false; 794 bool send_server_hello_msg = false;
1033 if (fd == server_listen_pipe_) { 795 if (fd == server_listen_pipe_) {
1034 int new_pipe = 0; 796 int new_pipe = 0;
1035 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe)) { 797 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe)) {
1036 Close(); 798 Close();
1037 listener_->OnChannelListenError(); 799 listener_->OnChannelListenError();
1038 } 800 }
1039 801
1040 if (pipe_ != -1) { 802 if (pipe_ != -1) {
1041 // We already have a connection. We only handle one at a time. 803 // We already have a connection. We only handle one at a time.
1042 // close our new descriptor. 804 // close our new descriptor.
1043 if (HANDLE_EINTR(shutdown(new_pipe, SHUT_RDWR)) < 0) 805 if (HANDLE_EINTR(shutdown(new_pipe, SHUT_RDWR)) < 0)
1044 PLOG(ERROR) << "shutdown " << pipe_name_; 806 DPLOG(ERROR) << "shutdown " << pipe_name_;
1045 if (HANDLE_EINTR(close(new_pipe)) < 0) 807 if (HANDLE_EINTR(close(new_pipe)) < 0)
1046 PLOG(ERROR) << "close " << pipe_name_; 808 DPLOG(ERROR) << "close " << pipe_name_;
1047 listener_->OnChannelDenied(); 809 listener_->OnChannelDenied();
1048 return; 810 return;
1049 } 811 }
1050 pipe_ = new_pipe; 812 pipe_ = new_pipe;
1051 813
1052 if ((mode_ & MODE_OPEN_ACCESS_FLAG) == 0) { 814 if ((mode_ & MODE_OPEN_ACCESS_FLAG) == 0) {
1053 // Verify that the IPC channel peer is running as the same user. 815 // Verify that the IPC channel peer is running as the same user.
1054 uid_t client_euid; 816 uid_t client_euid;
1055 if (!GetClientEuid(&client_euid)) { 817 if (!GetClientEuid(&client_euid)) {
1056 LOG(ERROR) << "Unable to query client euid"; 818 DLOG(ERROR) << "Unable to query client euid";
1057 ResetToAcceptingConnectionState(); 819 ResetToAcceptingConnectionState();
1058 return; 820 return;
1059 } 821 }
1060 if (client_euid != geteuid()) { 822 if (client_euid != geteuid()) {
1061 LOG(WARNING) << "Client euid is not authorised"; 823 DLOG(WARNING) << "Client euid is not authorised";
1062 ResetToAcceptingConnectionState(); 824 ResetToAcceptingConnectionState();
1063 return; 825 return;
1064 } 826 }
1065 } 827 }
1066 828
1067 if (!AcceptConnection()) { 829 if (!AcceptConnection()) {
1068 NOTREACHED() << "AcceptConnection should not fail on server"; 830 NOTREACHED() << "AcceptConnection should not fail on server";
1069 } 831 }
1070 send_server_hello_msg = true; 832 send_server_hello_msg = true;
1071 waiting_connect_ = false; 833 waiting_connect_ = false;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); 930 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
1169 } 931 }
1170 #endif // IPC_USES_READWRITE 932 #endif // IPC_USES_READWRITE
1171 output_queue_.push(msg.release()); 933 output_queue_.push(msg.release());
1172 } 934 }
1173 935
1174 bool Channel::ChannelImpl::IsHelloMessage(const Message* m) const { 936 bool Channel::ChannelImpl::IsHelloMessage(const Message* m) const {
1175 return m->routing_id() == MSG_ROUTING_NONE && m->type() == HELLO_MESSAGE_TYPE; 937 return m->routing_id() == MSG_ROUTING_NONE && m->type() == HELLO_MESSAGE_TYPE;
1176 } 938 }
1177 939
940 bool Channel::ChannelImpl::ReadDataFromPipe(const char** buffer_begin,
941 const char** buffer_end) {
942 struct msghdr msg = {0};
943
944 struct iovec iov = {input_buf_, Channel::kReadBufferSize};
945 msg.msg_iov = &iov;
946 msg.msg_iovlen = 1;
947
948 msg.msg_control = input_cmsg_buf_;
949
950 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data
951 // is waiting on the pipe.
952 ssize_t bytes_read = 0;
953 #if defined(IPC_USES_READWRITE)
954 if (fd_pipe_ >= 0) {
955 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_,
956 Channel::kReadBufferSize));
957 msg.msg_controllen = 0;
958 } else
959 #endif // IPC_USES_READWRITE
960 {
961 msg.msg_controllen = sizeof(input_cmsg_buf_);
962 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
963 }
964 if (bytes_read < 0) {
965 if (errno == EAGAIN) {
966 *buffer_begin = *buffer_end = NULL; // Signal no data was read.
967 return true;
968 #if defined(OS_MACOSX)
969 } else if (errno == EPERM) {
970 // On OSX, reading from a pipe with no listener returns EPERM
971 // treat this as a special case to prevent spurious error messages
972 // to the console.
973 return false;
974 #endif // OS_MACOSX
975 } else if (errno == ECONNRESET || errno == EPIPE) {
976 return false;
977 } else {
978 PLOG(ERROR) << "pipe error (" << pipe_ << ")";
979 return false;
980 }
981 } else if (bytes_read == 0) {
982 // The pipe has closed...
983 return false;
984 }
985 DCHECK(bytes_read);
986
987 CloseClientFileDescriptor();
988
989 // Read any file descriptors from the message.
990 if (!ExtractFileDescriptorsFromMsghdr(&msg))
991 return false;
992
993 // Possibly combine with the overflow buffer to make a larger buffer.
994 if (input_overflow_buf_.empty()) {
995 *buffer_begin = input_buf_;
996 *buffer_end = *buffer_begin + bytes_read;
997 } else {
998 if (input_overflow_buf_.size() > (kMaximumMessageSize - bytes_read)) {
999 input_overflow_buf_.clear();
1000 LOG(ERROR) << "IPC message is too big";
1001 return false;
1002 }
1003 input_overflow_buf_.append(input_buf_, bytes_read);
1004 *buffer_begin = input_overflow_buf_.data();
1005 *buffer_end = *buffer_begin + input_overflow_buf_.size();
1006 }
1007 return true;
1008 }
1009
1010 #if defined(IPC_USES_READWRITE)
1011 bool Channel::ChannelImpl::ReadFileDescriptorsFromFDPipe() {
1012 char dummy;
1013 struct iovec fd_pipe_iov = { &dummy, 1 };
1014
1015 struct msghdr msg = { 0 };
1016 msg.msg_iov = &fd_pipe_iov;
1017 msg.msg_iovlen = 1;
1018 msg.msg_control = input_cmsg_buf_;
1019 msg.msg_controllen = sizeof(input_cmsg_buf_);
1020 ssize_t bytes_received = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT));
1021
1022 if (bytes_received != 1)
1023 return true; // No message waiting.
1024
1025 if (!ExtractFileDescriptorsFromMsghdr(&msg))
1026 return false;
1027 return true;
1028 }
1029 #endif
1030
1031 bool Channel::ChannelImpl::PopulateMessageFileDescriptors(Message* msg) {
1032 uint16 header_fds = msg->header()->num_fds;
1033 if (!header_fds)
1034 return true; // Nothing to do.
1035
1036 // The message has file descriptors.
1037 const char* error = NULL;
1038 if (header_fds > input_fds_.size()) {
1039 // The message has been completely received, but we didn't get
1040 // enough file descriptors.
1041 #if defined(IPC_USES_READWRITE)
1042 if (!ReadFileDescriptorsFromFDPipe())
1043 return false;
1044 if (header_fds > input_fds_.size())
1045 #endif // IPC_USES_READWRITE
1046 error = "Message needs unreceived descriptors";
1047 }
1048
1049 if (header_fds > FileDescriptorSet::kMaxDescriptorsPerMessage)
1050 error = "Message requires an excessive number of descriptors";
1051
1052 if (error) {
1053 LOG(WARNING) << error
1054 << " channel:" << this
1055 << " message-type:" << msg->type()
1056 << " header()->num_fds:" << header_fds;
1057 #if defined(CHROMIUM_SELINUX)
1058 LOG(WARNING) << "In the case of SELinux this can be caused when "
1059 "using a --user-data-dir to which the default "
1060 "policy doesn't give the renderer access to. ";
1061 #endif // CHROMIUM_SELINUX
1062 // Abort the connection.
1063 ClearInputFDs();
1064 return false;
1065 }
1066
1067 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(),
1068 header_fds);
1069 input_fds_.erase(input_fds_.begin(), input_fds_.begin() + header_fds);
1070 return true;
1071 }
1072
1073 bool Channel::ChannelImpl::ExtractFileDescriptorsFromMsghdr(msghdr* msg) {
1074 // Check that there are any control messages. On OSX, CMSG_FIRSTHDR will
1075 // return an invalid non-NULL pointer in the case that controllen == 0.
1076 if (msg->msg_controllen == 0)
1077 return true;
1078
1079 for (cmsghdr* cmsg = CMSG_FIRSTHDR(msg);
1080 cmsg;
1081 cmsg = CMSG_NXTHDR(msg, cmsg)) {
1082 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
1083 unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
1084 DCHECK_EQ(0U, payload_len % sizeof(int));
1085 const int* file_descriptors = reinterpret_cast<int*>(CMSG_DATA(cmsg));
1086 unsigned num_file_descriptors = payload_len / 4;
1087 input_fds_.insert(input_fds_.end(),
1088 file_descriptors,
1089 file_descriptors + num_file_descriptors);
1090
1091 // Check this after adding the FDs so we don't leak them.
1092 if (msg->msg_flags & MSG_CTRUNC) {
1093 ClearInputFDs();
1094 return false;
1095 }
1096
1097 return true;
1098 }
1099 }
1100
1101 // No file descriptors found, but that's OK.
1102 return true;
1103 }
1104
1105 void Channel::ChannelImpl::ClearInputFDs() {
1106 while (!input_fds_.empty()) {
1107 if (HANDLE_EINTR(close(input_fds_.front())) < 0)
1108 PLOG(ERROR) << "close ";
1109 input_fds_.pop_front();
1110 }
1111 }
1112
1113 void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) {
1114 // The Hello message contains only the process id.
1115 void *iter = NULL;
1116 int pid;
1117 if (!msg.ReadInt(&iter, &pid))
1118 NOTREACHED();
1119
1120 #if defined(IPC_USES_READWRITE)
1121 if (mode_ & MODE_SERVER_FLAG) {
1122 // With IPC_USES_READWRITE, the Hello message from the client to the
1123 // server also contains the fd_pipe_, which will be used for all
1124 // subsequent file descriptor passing.
1125 DCHECK_EQ(msg.file_descriptor_set()->size(), 1U);
1126 base::FileDescriptor descriptor;
1127 if (!msg.ReadFileDescriptor(&iter, &descriptor)) {
1128 NOTREACHED();
1129 }
1130 fd_pipe_ = descriptor.fd;
1131 CHECK(descriptor.auto_close);
1132 }
1133 #endif // IPC_USES_READWRITE
1134 listener_->OnChannelConnected(pid);
1135 }
1136
1178 void Channel::ChannelImpl::Close() { 1137 void Channel::ChannelImpl::Close() {
1179 // Close can be called multiple time, so we need to make sure we're 1138 // Close can be called multiple time, so we need to make sure we're
1180 // idempotent. 1139 // idempotent.
1181 1140
1182 ResetToAcceptingConnectionState(); 1141 ResetToAcceptingConnectionState();
1183 1142
1184 if (must_unlink_) { 1143 if (must_unlink_) {
1185 unlink(pipe_name_.c_str()); 1144 unlink(pipe_name_.c_str());
1186 must_unlink_ = false; 1145 must_unlink_ = false;
1187 } 1146 }
1188 if (server_listen_pipe_ != -1) { 1147 if (server_listen_pipe_ != -1) {
1189 if (HANDLE_EINTR(close(server_listen_pipe_)) < 0) 1148 if (HANDLE_EINTR(close(server_listen_pipe_)) < 0)
1190 PLOG(ERROR) << "close " << server_listen_pipe_; 1149 DPLOG(ERROR) << "close " << server_listen_pipe_;
1191 server_listen_pipe_ = -1; 1150 server_listen_pipe_ = -1;
1192 // Unregister libevent for the listening socket and close it. 1151 // Unregister libevent for the listening socket and close it.
1193 server_listen_connection_watcher_.StopWatchingFileDescriptor(); 1152 server_listen_connection_watcher_.StopWatchingFileDescriptor();
1194 } 1153 }
1195 1154
1196 CloseClientFileDescriptor(); 1155 CloseClientFileDescriptor();
1197 } 1156 }
1198 1157
1199 //------------------------------------------------------------------------------ 1158 //------------------------------------------------------------------------------
1200 // Channel's methods simply call through to ChannelImpl. 1159 // Channel's methods simply call through to ChannelImpl.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 } 1212 }
1254 1213
1255 #if defined(OS_LINUX) 1214 #if defined(OS_LINUX)
1256 // static 1215 // static
1257 void Channel::SetGlobalPid(int pid) { 1216 void Channel::SetGlobalPid(int pid) {
1258 ChannelImpl::SetGlobalPid(pid); 1217 ChannelImpl::SetGlobalPid(pid);
1259 } 1218 }
1260 #endif // OS_LINUX 1219 #endif // OS_LINUX
1261 1220
1262 } // namespace IPC 1221 } // 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