ipc_channel_posix.h revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef IPC_IPC_CHANNEL_POSIX_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IPC_IPC_CHANNEL_POSIX_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> // for CMSG macros 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <queue> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/file_descriptor_set_posix.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_reader.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Linux, the seccomp sandbox makes it very expensive to call 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recvmsg() and sendmsg(). The restriction on calling read() and write(), which 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are cheap, is that we can't pass file descriptors over them. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As we cannot anticipate when the sender will provide us with file 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descriptors, we have to make the decision about whether we call read() or 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recvmsg() before we actually make the call. The easiest option is to 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// create a dedicated socketpair() for exchanging file descriptors. Any file 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descriptors are split out of a message, with the non-file-descriptor payload 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// going over the normal connection, and the file descriptors being sent 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// separately over the other channel. When read()ing from a channel, we'll 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice if the message was supposed to have come with file descriptors and 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use recvmsg on the other socketpair to retrieve them and combine them 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// back with the rest of the message. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mac can also run in IPC_USES_READWRITE mode if necessary, but at this time 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// doesn't take a performance hit from recvmsg and sendmsg, so it doesn't 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// make sense to waste resources on having the separate dedicated socketpair. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is however useful for debugging between Linux and Mac to be able to turn 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this switch 'on' on the Mac as well. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The HELLO message from the client to the server is always sent using 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sendmsg because it will contain the file descriptor that the server 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needs to send file descriptors in later messages. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IPC_USES_READWRITE 1 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IPC { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Channel::ChannelImpl : public internal::ChannelReader, 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public base::MessageLoopForIO::Watcher { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mirror methods of Channel, see ipc_channel.h for description. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelImpl(const IPC::ChannelHandle& channel_handle, Mode mode, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Listener* listener); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ChannelImpl(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Connect(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Close(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Send(Message* message); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int GetClientFileDescriptor(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int TakeClientFileDescriptor(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CloseClientFileDescriptor(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool AcceptsConnections() const; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool HasAcceptedConnection() const; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool GetPeerEuid(uid_t* peer_euid) const; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ResetToAcceptingConnectionState(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessId peer_pid() const { return peer_pid_; } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsNamedServerInitialized(const std::string& channel_id); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void SetGlobalPid(int pid); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_LINUX 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool CreatePipe(const IPC::ChannelHandle& channel_handle); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ProcessOutgoingMessages(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool AcceptConnection(); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ClosePipeOnError(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int GetHelloMessageProcId(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void QueueHelloMessage(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ChannelReader implementation. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ReadState ReadData(char* buffer, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_len, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* bytes_read) OVERRIDE; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool WillDispatchInputMessage(Message* msg) OVERRIDE; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool DidEmptyInputBuffers() OVERRIDE; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void HandleHelloMessage(const Message& msg) OVERRIDE; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(IPC_USES_READWRITE) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reads the next message from the fd_pipe_ and appends them to the 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // input_fds_ queue. Returns false if there was a message receiving error. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True means there was a message and it was processed properly, or there was 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no messages. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ReadFileDescriptorsFromFDPipe(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finds the set of file descriptors in the given message. On success, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appends the descriptors to the input_fds_ member and returns true 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns false if the message was truncated. In this case, any handles that 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // were sent will be closed. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ExtractFileDescriptorsFromMsghdr(msghdr* msg); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Closes all handles in the input_fds_ list and clears the list. This is 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // used to clean up handles in error conditions to avoid leaking the handles. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ClearInputFDs(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MessageLoopForIO::Watcher implementation. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mode mode_; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessId peer_pid_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After accepting one client connection on our server socket we want to 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stop listening. 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO::FileDescriptorWatcher 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) server_listen_connection_watcher_; 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO::FileDescriptorWatcher read_watcher_; 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO::FileDescriptorWatcher write_watcher_; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether we're currently blocked waiting for a write to complete. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_blocked_on_write_; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool waiting_connect_; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If sending a message blocks then we use this variable 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to keep track of where we are. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t message_send_bytes_written_; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // File descriptor we're listening on for new connections if we listen 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for connections. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int server_listen_pipe_; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The pipe used for communication. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pipe_; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For a server, the client end of our socketpair() -- the other end of our 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pipe_ that is passed to the client. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int client_pipe_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock client_pipe_lock_; // Lock that protects |client_pipe_|. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(IPC_USES_READWRITE) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Linux/BSD use a dedicated socketpair() for passing file descriptors. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd_pipe_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int remote_fd_pipe_; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The "name" of our pipe. On Windows this is the global identifier for 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the pipe. On POSIX it's used as a key in a local map of file descriptors. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string pipe_name_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Messages to be sent are queued here. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<Message*> output_queue_; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We assume a worst case: kReadBufferSize bytes of messages, where each 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message has no payload and a full complement of descriptors. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kMaxReadFDs = 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) * 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileDescriptorSet::kMaxDescriptorsPerMessage; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Buffer size for file descriptors used for recvmsg. On Mac the CMSG macros 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't seem to be constant so we have to pick a "large enough" value. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kMaxReadFDBuffer = 1024; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kMaxReadFDBuffer = CMSG_SPACE(sizeof(int) * kMaxReadFDs); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Temporary buffer used to receive the file descriptors from recvmsg. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Code that writes into this should immediately read them out and save 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them to input_fds_, since this buffer will be re-used anytime we call 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recvmsg. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char input_cmsg_buf_[kMaxReadFDBuffer]; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // File descriptors extracted from messages coming off of the channel. The 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handles may span messages and come off different channels from the message 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data (in the case of READWRITE), and are processed in FIFO here. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: The implementation assumes underlying storage here is contiguous, so 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't change to something like std::deque<> without changing the 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // implementation! 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> input_fds_; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True if we are responsible for unlinking the unix domain socket file. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool must_unlink_; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If non-zero, overrides the process ID sent in the hello message. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int global_pid_; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_LINUX 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelImpl); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace IPC 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // IPC_IPC_CHANNEL_POSIX_H_ 201