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/types.h> | 10 #include <sys/types.h> |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |