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 3 // found in the LICENSE file. 4 5 #ifndef IPC_IPC_CHANNEL_POSIX_H_ 6 #define IPC_IPC_CHANNEL_POSIX_H_ 7 8 #include "ipc/ipc_channel.h" 9 10 #include <sys/socket.h> // for CMSG macros 11 12 #include <queue> 13 #include <string> 14 #include <vector> 15 16 #include "base/message_loop/message_loop.h" 17 #include "base/process/process.h" 18 #include "ipc/file_descriptor_set_posix.h" 19 #include "ipc/ipc_channel_reader.h" 20 21 #if !defined(OS_MACOSX) 22 // On Linux, the seccomp sandbox makes it very expensive to call 23 // recvmsg() and sendmsg(). The restriction on calling read() and write(), which 24 // are cheap, is that we can't pass file descriptors over them. 25 // 26 // As we cannot anticipate when the sender will provide us with file 27 // descriptors, we have to make the decision about whether we call read() or 28 // recvmsg() before we actually make the call. The easiest option is to 29 // create a dedicated socketpair() for exchanging file descriptors. Any file 30 // descriptors are split out of a message, with the non-file-descriptor payload 31 // going over the normal connection, and the file descriptors being sent 32 // separately over the other channel. When read()ing from a channel, we'll 33 // notice if the message was supposed to have come with file descriptors and 34 // use recvmsg on the other socketpair to retrieve them and combine them 35 // back with the rest of the message. 36 // 37 // Mac can also run in IPC_USES_READWRITE mode if necessary, but at this time 38 // doesn't take a performance hit from recvmsg and sendmsg, so it doesn't 39 // make sense to waste resources on having the separate dedicated socketpair. 40 // It is however useful for debugging between Linux and Mac to be able to turn 41 // this switch 'on' on the Mac as well. 42 // 43 // The HELLO message from the client to the server is always sent using 44 // sendmsg because it will contain the file descriptor that the server 45 // needs to send file descriptors in later messages. 46 #define IPC_USES_READWRITE 1 47 #endif 48 49 namespace IPC { 50 51 class Channel::ChannelImpl : public internal::ChannelReader, 52 public base::MessageLoopForIO::Watcher { 53 public: 54 // Mirror methods of Channel, see ipc_channel.h for description. 55 ChannelImpl(const IPC::ChannelHandle& channel_handle, Mode mode, 56 Listener* listener); 57 virtual ~ChannelImpl(); 58 bool Connect(); 59 void Close(); 60 bool Send(Message* message); 61 int GetClientFileDescriptor(); 62 int TakeClientFileDescriptor(); 63 void CloseClientFileDescriptor(); 64 bool AcceptsConnections() const; 65 bool HasAcceptedConnection() const; 66 bool GetPeerEuid(uid_t* peer_euid) const; 67 void ResetToAcceptingConnectionState(); 68 base::ProcessId peer_pid() const { return peer_pid_; } 69 static bool IsNamedServerInitialized(const std::string& channel_id); 70 #if defined(OS_LINUX) 71 static void SetGlobalPid(int pid); 72 #endif // OS_LINUX 73 74 private: 75 bool CreatePipe(const IPC::ChannelHandle& channel_handle); 76 77 bool ProcessOutgoingMessages(); 78 79 bool AcceptConnection(); 80 void ClosePipeOnError(); 81 int GetHelloMessageProcId(); 82 void QueueHelloMessage(); 83 84 // ChannelReader implementation. 85 virtual ReadState ReadData(char* buffer, 86 int buffer_len, 87 int* bytes_read) OVERRIDE; 88 virtual bool WillDispatchInputMessage(Message* msg) OVERRIDE; 89 virtual bool DidEmptyInputBuffers() OVERRIDE; 90 virtual void HandleHelloMessage(const Message& msg) OVERRIDE; 91 92 #if defined(IPC_USES_READWRITE) 93 // Reads the next message from the fd_pipe_ and appends them to the 94 // input_fds_ queue. Returns false if there was a message receiving error. 95 // True means there was a message and it was processed properly, or there was 96 // no messages. 97 bool ReadFileDescriptorsFromFDPipe(); 98 #endif 99 100 // Finds the set of file descriptors in the given message. On success, 101 // appends the descriptors to the input_fds_ member and returns true 102 // 103 // Returns false if the message was truncated. In this case, any handles that 104 // were sent will be closed. 105 bool ExtractFileDescriptorsFromMsghdr(msghdr* msg); 106 107 // Closes all handles in the input_fds_ list and clears the list. This is 108 // used to clean up handles in error conditions to avoid leaking the handles. 109 void ClearInputFDs(); 110 111 // MessageLoopForIO::Watcher implementation. 112 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; 113 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; 114 115 Mode mode_; 116 117 base::ProcessId peer_pid_; 118 119 // After accepting one client connection on our server socket we want to 120 // stop listening. 121 base::MessageLoopForIO::FileDescriptorWatcher 122 server_listen_connection_watcher_; 123 base::MessageLoopForIO::FileDescriptorWatcher read_watcher_; 124 base::MessageLoopForIO::FileDescriptorWatcher write_watcher_; 125 126 // Indicates whether we're currently blocked waiting for a write to complete. 127 bool is_blocked_on_write_; 128 bool waiting_connect_; 129 130 // If sending a message blocks then we use this variable 131 // to keep track of where we are. 132 size_t message_send_bytes_written_; 133 134 // File descriptor we're listening on for new connections if we listen 135 // for connections. 136 int server_listen_pipe_; 137 138 // The pipe used for communication. 139 int pipe_; 140 141 // For a server, the client end of our socketpair() -- the other end of our 142 // pipe_ that is passed to the client. 143 int client_pipe_; 144 base::Lock client_pipe_lock_; // Lock that protects |client_pipe_|. 145 146 #if defined(IPC_USES_READWRITE) 147 // Linux/BSD use a dedicated socketpair() for passing file descriptors. 148 int fd_pipe_; 149 int remote_fd_pipe_; 150 #endif 151 152 // The "name" of our pipe. On Windows this is the global identifier for 153 // the pipe. On POSIX it's used as a key in a local map of file descriptors. 154 std::string pipe_name_; 155 156 // Messages to be sent are queued here. 157 std::queue<Message*> output_queue_; 158 159 // We assume a worst case: kReadBufferSize bytes of messages, where each 160 // message has no payload and a full complement of descriptors. 161 static const size_t kMaxReadFDs = 162 (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) * 163 FileDescriptorSet::kMaxDescriptorsPerMessage; 164 165 // Buffer size for file descriptors used for recvmsg. On Mac the CMSG macros 166 // don't seem to be constant so we have to pick a "large enough" value. 167 #if defined(OS_MACOSX) 168 static const size_t kMaxReadFDBuffer = 1024; 169 #else 170 static const size_t kMaxReadFDBuffer = CMSG_SPACE(sizeof(int) * kMaxReadFDs); 171 #endif 172 173 // Temporary buffer used to receive the file descriptors from recvmsg. 174 // Code that writes into this should immediately read them out and save 175 // them to input_fds_, since this buffer will be re-used anytime we call 176 // recvmsg. 177 char input_cmsg_buf_[kMaxReadFDBuffer]; 178 179 // File descriptors extracted from messages coming off of the channel. The 180 // handles may span messages and come off different channels from the message 181 // data (in the case of READWRITE), and are processed in FIFO here. 182 // NOTE: The implementation assumes underlying storage here is contiguous, so 183 // don't change to something like std::deque<> without changing the 184 // implementation! 185 std::vector<int> input_fds_; 186 187 // True if we are responsible for unlinking the unix domain socket file. 188 bool must_unlink_; 189 190 #if defined(OS_LINUX) 191 // If non-zero, overrides the process ID sent in the hello message. 192 static int global_pid_; 193 #endif // OS_LINUX 194 195 DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelImpl); 196 }; 197 198 } // namespace IPC 199 200 #endif // IPC_IPC_CHANNEL_POSIX_H_ 201