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