Chromium Code Reviews| 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 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 true, | 340 true, |
| 341 base::MessageLoopForIO::WATCH_READ, | 341 base::MessageLoopForIO::WATCH_READ, |
| 342 &server_listen_connection_watcher_, | 342 &server_listen_connection_watcher_, |
| 343 this); | 343 this); |
| 344 } else { | 344 } else { |
| 345 did_connect = AcceptConnection(); | 345 did_connect = AcceptConnection(); |
| 346 } | 346 } |
| 347 return did_connect; | 347 return did_connect; |
| 348 } | 348 } |
| 349 | 349 |
| 350 void Channel::ChannelImpl::CloseFileDescriptors(Message* msg) { | |
| 351 #if defined(OS_MACOSX) | |
| 352 // There is a bug on OSX which makes it dangerous to close | |
| 353 // a file descriptor while it is in transit. So instead we | |
| 354 // store the file descriptor in a set and send a message to | |
| 355 // the recipient, which is queued AFTER the message that | |
| 356 // sent the FD. The recipient will reply to the message, | |
| 357 // letting us know that it is now safe to close the file | |
| 358 // descriptor. For more information, see: | |
| 359 // http://crbug.com/298276 | |
| 360 std::vector<int> to_close; | |
| 361 msg->file_descriptor_set()->GetFDsToCloseAndClear(&to_close); | |
| 362 for (size_t i = 0; i < to_close.size(); i++) { | |
| 363 fds_to_close_.insert(to_close[i]); | |
| 364 QueueCloseFDMessage(to_close[i], 2); | |
| 365 } | |
| 366 #else | |
| 367 msg->file_descriptor_set()->CommitAll(); | |
| 368 #endif | |
| 369 } | |
| 370 | |
|
agl
2013/10/09 21:52:38
this file only has a single newline after function
hubbe
2013/10/09 21:59:40
Done.
| |
| 371 | |
| 350 bool Channel::ChannelImpl::ProcessOutgoingMessages() { | 372 bool Channel::ChannelImpl::ProcessOutgoingMessages() { |
| 351 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's | 373 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's |
| 352 // no connection? | 374 // no connection? |
| 353 if (output_queue_.empty()) | 375 if (output_queue_.empty()) |
| 354 return true; | 376 return true; |
| 355 | 377 |
| 356 if (pipe_ == -1) | 378 if (pipe_ == -1) |
| 357 return false; | 379 return false; |
| 358 | 380 |
| 359 // Write out all the messages we can till the write blocks or there are no | 381 // Write out all the messages we can till the write blocks or there are no |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 412 // Only the Hello message sends the file descriptor with the message. | 434 // Only the Hello message sends the file descriptor with the message. |
| 413 // Subsequently, we can send file descriptors on the dedicated | 435 // Subsequently, we can send file descriptors on the dedicated |
| 414 // fd_pipe_ which makes Seccomp sandbox operation more efficient. | 436 // fd_pipe_ which makes Seccomp sandbox operation more efficient. |
| 415 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; | 437 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; |
| 416 msgh.msg_iov = &fd_pipe_iov; | 438 msgh.msg_iov = &fd_pipe_iov; |
| 417 fd_written = fd_pipe_; | 439 fd_written = fd_pipe_; |
| 418 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); | 440 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); |
| 419 msgh.msg_iov = &iov; | 441 msgh.msg_iov = &iov; |
| 420 msgh.msg_controllen = 0; | 442 msgh.msg_controllen = 0; |
| 421 if (bytes_written > 0) { | 443 if (bytes_written > 0) { |
| 422 msg->file_descriptor_set()->CommitAll(); | 444 CloseFileDescriptors(msg); |
| 423 } | 445 } |
| 424 } | 446 } |
| 425 #endif // IPC_USES_READWRITE | 447 #endif // IPC_USES_READWRITE |
| 426 } | 448 } |
| 427 | 449 |
| 428 if (bytes_written == 1) { | 450 if (bytes_written == 1) { |
| 429 fd_written = pipe_; | 451 fd_written = pipe_; |
| 430 #if defined(IPC_USES_READWRITE) | 452 #if defined(IPC_USES_READWRITE) |
| 431 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) { | 453 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) { |
| 432 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); | 454 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); |
| 433 } | 455 } |
| 434 if (!msgh.msg_controllen) { | 456 if (!msgh.msg_controllen) { |
| 435 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); | 457 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); |
| 436 } else | 458 } else |
| 437 #endif // IPC_USES_READWRITE | 459 #endif // IPC_USES_READWRITE |
| 438 { | 460 { |
| 439 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT)); | 461 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT)); |
| 440 } | 462 } |
| 441 } | 463 } |
| 442 if (bytes_written > 0) | 464 if (bytes_written > 0) |
| 443 msg->file_descriptor_set()->CommitAll(); | 465 CloseFileDescriptors(msg); |
| 444 | 466 |
| 445 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { | 467 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { |
| 446 #if defined(OS_MACOSX) | 468 #if defined(OS_MACOSX) |
| 447 // On OSX writing to a pipe with no listener returns EPERM. | 469 // On OSX writing to a pipe with no listener returns EPERM. |
| 448 if (errno == EPERM) { | 470 if (errno == EPERM) { |
| 449 Close(); | 471 Close(); |
| 450 return false; | 472 return false; |
| 451 } | 473 } |
| 452 #endif // OS_MACOSX | 474 #endif // OS_MACOSX |
| 453 if (errno == EPIPE) { | 475 if (errno == EPIPE) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 568 #endif // IPC_USES_READWRITE | 590 #endif // IPC_USES_READWRITE |
| 569 | 591 |
| 570 while (!output_queue_.empty()) { | 592 while (!output_queue_.empty()) { |
| 571 Message* m = output_queue_.front(); | 593 Message* m = output_queue_.front(); |
| 572 output_queue_.pop(); | 594 output_queue_.pop(); |
| 573 delete m; | 595 delete m; |
| 574 } | 596 } |
| 575 | 597 |
| 576 // Close any outstanding, received file descriptors. | 598 // Close any outstanding, received file descriptors. |
| 577 ClearInputFDs(); | 599 ClearInputFDs(); |
| 600 | |
| 601 #if defined(OS_MACOSX) | |
| 602 // Clear any outstanding, sent file descriptors. | |
| 603 for (std::set<int>::iterator i = fds_to_close_.begin(); | |
| 604 i != fds_to_close_.end(); | |
| 605 ++i) { | |
| 606 if (HANDLE_EINTR(close(*i)) < 0) | |
| 607 PLOG(ERROR) << "close"; | |
| 608 } | |
| 609 fds_to_close_.clear(); | |
| 610 #endif | |
| 578 } | 611 } |
| 579 | 612 |
| 580 // static | 613 // static |
| 581 bool Channel::ChannelImpl::IsNamedServerInitialized( | 614 bool Channel::ChannelImpl::IsNamedServerInitialized( |
| 582 const std::string& channel_id) { | 615 const std::string& channel_id) { |
| 583 return base::PathExists(base::FilePath(channel_id)); | 616 return base::PathExists(base::FilePath(channel_id)); |
| 584 } | 617 } |
| 585 | 618 |
| 586 #if defined(OS_LINUX) | 619 #if defined(OS_LINUX) |
| 587 // static | 620 // static |
| 588 void Channel::ChannelImpl::SetGlobalPid(int pid) { | 621 void Channel::ChannelImpl::SetGlobalPid(int pid) { |
| 589 global_pid_ = pid; | 622 global_pid_ = pid; |
| 590 } | 623 } |
| 591 #endif // OS_LINUX | 624 #endif // OS_LINUX |
| 592 | 625 |
| 593 // Called by libevent when we can read from the pipe without blocking. | 626 // Called by libevent when we can read from the pipe without blocking. |
| 594 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { | 627 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { |
| 595 bool send_server_hello_msg = false; | |
| 596 if (fd == server_listen_pipe_) { | 628 if (fd == server_listen_pipe_) { |
| 597 int new_pipe = 0; | 629 int new_pipe = 0; |
| 598 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe) || | 630 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe) || |
| 599 new_pipe < 0) { | 631 new_pipe < 0) { |
| 600 Close(); | 632 Close(); |
| 601 listener()->OnChannelListenError(); | 633 listener()->OnChannelListenError(); |
| 602 } | 634 } |
| 603 | 635 |
| 604 if (pipe_ != -1) { | 636 if (pipe_ != -1) { |
| 605 // We already have a connection. We only handle one at a time. | 637 // We already have a connection. We only handle one at a time. |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 624 if (client_euid != geteuid()) { | 656 if (client_euid != geteuid()) { |
| 625 DLOG(WARNING) << "Client euid is not authorised"; | 657 DLOG(WARNING) << "Client euid is not authorised"; |
| 626 ResetToAcceptingConnectionState(); | 658 ResetToAcceptingConnectionState(); |
| 627 return; | 659 return; |
| 628 } | 660 } |
| 629 } | 661 } |
| 630 | 662 |
| 631 if (!AcceptConnection()) { | 663 if (!AcceptConnection()) { |
| 632 NOTREACHED() << "AcceptConnection should not fail on server"; | 664 NOTREACHED() << "AcceptConnection should not fail on server"; |
| 633 } | 665 } |
| 634 send_server_hello_msg = true; | |
| 635 waiting_connect_ = false; | 666 waiting_connect_ = false; |
| 636 } else if (fd == pipe_) { | 667 } else if (fd == pipe_) { |
| 637 if (waiting_connect_ && (mode_ & MODE_SERVER_FLAG)) { | 668 if (waiting_connect_ && (mode_ & MODE_SERVER_FLAG)) { |
| 638 send_server_hello_msg = true; | |
| 639 waiting_connect_ = false; | 669 waiting_connect_ = false; |
| 640 } | 670 } |
| 641 if (!ProcessIncomingMessages()) { | 671 if (!ProcessIncomingMessages()) { |
| 642 // ClosePipeOnError may delete this object, so we mustn't call | 672 // ClosePipeOnError may delete this object, so we mustn't call |
| 643 // ProcessOutgoingMessages. | 673 // ProcessOutgoingMessages. |
| 644 send_server_hello_msg = false; | |
| 645 ClosePipeOnError(); | 674 ClosePipeOnError(); |
| 675 return; | |
| 646 } | 676 } |
| 647 } else { | 677 } else { |
| 648 NOTREACHED() << "Unknown pipe " << fd; | 678 NOTREACHED() << "Unknown pipe " << fd; |
| 649 } | 679 } |
| 650 | 680 |
| 651 // If we're a server and handshaking, then we want to make sure that we | 681 // If we're a server and handshaking, then we want to make sure that we |
| 652 // only send our handshake message after we've processed the client's. | 682 // only send our handshake message after we've processed the client's. |
| 653 // This gives us a chance to kill the client if the incoming handshake | 683 // This gives us a chance to kill the client if the incoming handshake |
| 654 // is invalid. | 684 // is invalid. This also flushes any closefd messagse. |
| 655 if (send_server_hello_msg) { | 685 if (!is_blocked_on_write_) { |
| 656 ProcessOutgoingMessages(); | 686 ProcessOutgoingMessages(); |
| 657 } | 687 } |
| 658 } | 688 } |
| 659 | 689 |
| 660 // Called by libevent when we can write to the pipe without blocking. | 690 // Called by libevent when we can write to the pipe without blocking. |
| 661 void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) { | 691 void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) { |
| 662 DCHECK_EQ(pipe_, fd); | 692 DCHECK_EQ(pipe_, fd); |
| 663 is_blocked_on_write_ = false; | 693 is_blocked_on_write_ = false; |
| 664 if (!ProcessOutgoingMessages()) { | 694 if (!ProcessOutgoingMessages()) { |
| 665 ClosePipeOnError(); | 695 ClosePipeOnError(); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 895 } | 925 } |
| 896 | 926 |
| 897 void Channel::ChannelImpl::ClearInputFDs() { | 927 void Channel::ChannelImpl::ClearInputFDs() { |
| 898 for (size_t i = 0; i < input_fds_.size(); ++i) { | 928 for (size_t i = 0; i < input_fds_.size(); ++i) { |
| 899 if (HANDLE_EINTR(close(input_fds_[i])) < 0) | 929 if (HANDLE_EINTR(close(input_fds_[i])) < 0) |
| 900 PLOG(ERROR) << "close "; | 930 PLOG(ERROR) << "close "; |
| 901 } | 931 } |
| 902 input_fds_.clear(); | 932 input_fds_.clear(); |
| 903 } | 933 } |
| 904 | 934 |
| 905 void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) { | 935 void Channel::ChannelImpl::QueueCloseFDMessage(int fd, int hops) { |
| 936 switch (hops) { | |
| 937 case 1: | |
| 938 case 2: { | |
| 939 // Create the message | |
| 940 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | |
| 941 CLOSE_FD_MESSAGE_TYPE, | |
| 942 IPC::Message::PRIORITY_NORMAL)); | |
| 943 if (!msg->WriteInt(hops - 1) || !msg->WriteInt(fd)) { | |
| 944 NOTREACHED() << "Unable to pickle close fd."; | |
| 945 } | |
| 946 // Send(msg.release()); | |
| 947 output_queue_.push(msg.release()); | |
| 948 break; | |
| 949 } | |
| 950 | |
| 951 default: | |
| 952 NOTREACHED(); | |
| 953 break; | |
| 954 } | |
| 955 } | |
| 956 | |
| 957 void Channel::ChannelImpl::HandleInternalMessage(const Message& msg) { | |
| 906 // The Hello message contains only the process id. | 958 // The Hello message contains only the process id. |
| 907 PickleIterator iter(msg); | 959 PickleIterator iter(msg); |
| 908 int pid; | 960 |
| 909 if (!msg.ReadInt(&iter, &pid)) | 961 switch (msg.type()) { |
| 910 NOTREACHED(); | 962 default: |
| 963 NOTREACHED(); | |
| 964 break; | |
| 965 | |
| 966 case Channel::HELLO_MESSAGE_TYPE: | |
| 967 int pid; | |
| 968 if (!msg.ReadInt(&iter, &pid)) | |
| 969 NOTREACHED(); | |
| 911 | 970 |
| 912 #if defined(IPC_USES_READWRITE) | 971 #if defined(IPC_USES_READWRITE) |
| 913 if (mode_ & MODE_SERVER_FLAG) { | 972 if (mode_ & MODE_SERVER_FLAG) { |
| 914 // With IPC_USES_READWRITE, the Hello message from the client to the | 973 // With IPC_USES_READWRITE, the Hello message from the client to the |
| 915 // server also contains the fd_pipe_, which will be used for all | 974 // server also contains the fd_pipe_, which will be used for all |
| 916 // subsequent file descriptor passing. | 975 // subsequent file descriptor passing. |
| 917 DCHECK_EQ(msg.file_descriptor_set()->size(), 1U); | 976 DCHECK_EQ(msg.file_descriptor_set()->size(), 1U); |
| 918 base::FileDescriptor descriptor; | 977 base::FileDescriptor descriptor; |
| 919 if (!msg.ReadFileDescriptor(&iter, &descriptor)) { | 978 if (!msg.ReadFileDescriptor(&iter, &descriptor)) { |
| 920 NOTREACHED(); | 979 NOTREACHED(); |
| 921 } | 980 } |
| 922 fd_pipe_ = descriptor.fd; | 981 fd_pipe_ = descriptor.fd; |
| 923 CHECK(descriptor.auto_close); | 982 CHECK(descriptor.auto_close); |
| 983 } | |
| 984 #endif // IPC_USES_READWRITE | |
| 985 peer_pid_ = pid; | |
| 986 listener()->OnChannelConnected(pid); | |
| 987 break; | |
| 988 | |
| 989 #if defined(OS_MACOSX) | |
| 990 case Channel::CLOSE_FD_MESSAGE_TYPE: | |
| 991 int fd, hops; | |
| 992 if (!msg.ReadInt(&iter, &hops)) | |
| 993 NOTREACHED(); | |
| 994 if (!msg.ReadInt(&iter, &fd)) | |
| 995 NOTREACHED(); | |
| 996 if (hops == 0) { | |
| 997 if (fds_to_close_.erase(fd) > 0) { | |
| 998 if (HANDLE_EINTR(close(fd)) < 0) | |
| 999 PLOG(ERROR) << "close"; | |
| 1000 } else { | |
| 1001 NOTREACHED(); | |
| 1002 } | |
| 1003 } else { | |
| 1004 QueueCloseFDMessage(fd, hops); | |
| 1005 } | |
| 1006 break; | |
| 1007 #endif | |
| 924 } | 1008 } |
| 925 #endif // IPC_USES_READWRITE | |
| 926 peer_pid_ = pid; | |
| 927 listener()->OnChannelConnected(pid); | |
| 928 } | 1009 } |
| 929 | 1010 |
| 930 void Channel::ChannelImpl::Close() { | 1011 void Channel::ChannelImpl::Close() { |
| 931 // Close can be called multiple time, so we need to make sure we're | 1012 // Close can be called multiple time, so we need to make sure we're |
| 932 // idempotent. | 1013 // idempotent. |
| 933 | 1014 |
| 934 ResetToAcceptingConnectionState(); | 1015 ResetToAcceptingConnectionState(); |
| 935 | 1016 |
| 936 if (must_unlink_) { | 1017 if (must_unlink_) { |
| 937 unlink(pipe_name_.c_str()); | 1018 unlink(pipe_name_.c_str()); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1019 | 1100 |
| 1020 | 1101 |
| 1021 #if defined(OS_LINUX) | 1102 #if defined(OS_LINUX) |
| 1022 // static | 1103 // static |
| 1023 void Channel::SetGlobalPid(int pid) { | 1104 void Channel::SetGlobalPid(int pid) { |
| 1024 ChannelImpl::SetGlobalPid(pid); | 1105 ChannelImpl::SetGlobalPid(pid); |
| 1025 } | 1106 } |
| 1026 #endif // OS_LINUX | 1107 #endif // OS_LINUX |
| 1027 | 1108 |
| 1028 } // namespace IPC | 1109 } // namespace IPC |
| OLD | NEW |