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 IPC_EXPORT ChannelPosix : public Channel, 53 public internal::ChannelReader, 54 public base::MessageLoopForIO::Watcher { 55 public: 56 ChannelPosix(const IPC::ChannelHandle& channel_handle, Mode mode, 57 Listener* listener); 58 virtual ~ChannelPosix(); 59 60 // Channel implementation 61 virtual bool Connect() OVERRIDE; 62 virtual void Close() OVERRIDE; 63 virtual bool Send(Message* message) OVERRIDE; 64 virtual base::ProcessId GetPeerPID() const OVERRIDE; 65 virtual base::ProcessId GetSelfPID() const OVERRIDE; 66 virtual int GetClientFileDescriptor() const OVERRIDE; 67 virtual int TakeClientFileDescriptor() OVERRIDE; 68 69 // Returns true if the channel supports listening for connections. 70 bool AcceptsConnections() const; 71 72 // Returns true if the channel supports listening for connections and is 73 // currently connected. 74 bool HasAcceptedConnection() const; 75 76 // Closes any currently connected socket, and returns to a listening state 77 // for more connections. 78 void ResetToAcceptingConnectionState(); 79 80 // Returns true if the peer process' effective user id can be determined, in 81 // which case the supplied peer_euid is updated with it. 82 bool GetPeerEuid(uid_t* peer_euid) const; 83 84 void CloseClientFileDescriptor(); 85 86 static bool IsNamedServerInitialized(const std::string& channel_id); 87 #if defined(OS_LINUX) 88 static void SetGlobalPid(int pid); 89 #endif // OS_LINUX 90 91 private: 92 bool CreatePipe(const IPC::ChannelHandle& channel_handle); 93 94 bool ProcessOutgoingMessages(); 95 96 bool AcceptConnection(); 97 void ClosePipeOnError(); 98 int GetHelloMessageProcId() const; 99 void QueueHelloMessage(); 100 void CloseFileDescriptors(Message* msg); 101 void QueueCloseFDMessage(int fd, int hops); 102 103 // ChannelReader implementation. 104 virtual ReadState ReadData(char* buffer, 105 int buffer_len, 106 int* bytes_read) OVERRIDE; 107 virtual bool WillDispatchInputMessage(Message* msg) OVERRIDE; 108 virtual bool DidEmptyInputBuffers() OVERRIDE; 109 virtual void HandleInternalMessage(const Message& msg) OVERRIDE; 110 111 #if defined(IPC_USES_READWRITE) 112 // Reads the next message from the fd_pipe_ and appends them to the 113 // input_fds_ queue. Returns false if there was a message receiving error. 114 // True means there was a message and it was processed properly, or there was 115 // no messages. 116 bool ReadFileDescriptorsFromFDPipe(); 117 #endif 118 119 // Finds the set of file descriptors in the given message. On success, 120 // appends the descriptors to the input_fds_ member and returns true 121 // 122 // Returns false if the message was truncated. In this case, any handles that 123 // were sent will be closed. 124 bool ExtractFileDescriptorsFromMsghdr(msghdr* msg); 125 126 // Closes all handles in the input_fds_ list and clears the list. This is 127 // used to clean up handles in error conditions to avoid leaking the handles. 128 void ClearInputFDs(); 129 130 // MessageLoopForIO::Watcher implementation. 131 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; 132 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; 133 134 Mode mode_; 135 136 base::ProcessId peer_pid_; 137 138 // After accepting one client connection on our server socket we want to 139 // stop listening. 140 base::MessageLoopForIO::FileDescriptorWatcher 141 server_listen_connection_watcher_; 142 base::MessageLoopForIO::FileDescriptorWatcher read_watcher_; 143 base::MessageLoopForIO::FileDescriptorWatcher write_watcher_; 144 145 // Indicates whether we're currently blocked waiting for a write to complete. 146 bool is_blocked_on_write_; 147 bool waiting_connect_; 148 149 // If sending a message blocks then we use this variable 150 // to keep track of where we are. 151 size_t message_send_bytes_written_; 152 153 // File descriptor we're listening on for new connections if we listen 154 // for connections. 155 int server_listen_pipe_; 156 157 // The pipe used for communication. 158 int pipe_; 159 160 // For a server, the client end of our socketpair() -- the other end of our 161 // pipe_ that is passed to the client. 162 int client_pipe_; 163 mutable base::Lock client_pipe_lock_; // Lock that protects |client_pipe_|. 164 165 #if defined(IPC_USES_READWRITE) 166 // Linux/BSD use a dedicated socketpair() for passing file descriptors. 167 int fd_pipe_; 168 int remote_fd_pipe_; 169 #endif 170 171 // The "name" of our pipe. On Windows this is the global identifier for 172 // the pipe. On POSIX it's used as a key in a local map of file descriptors. 173 std::string pipe_name_; 174 175 // Messages to be sent are queued here. 176 std::queue<Message*> output_queue_; 177 178 // We assume a worst case: kReadBufferSize bytes of messages, where each 179 // message has no payload and a full complement of descriptors. 180 static const size_t kMaxReadFDs = 181 (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) * 182 FileDescriptorSet::kMaxDescriptorsPerMessage; 183 184 // Buffer size for file descriptors used for recvmsg. On Mac the CMSG macros 185 // don't seem to be constant so we have to pick a "large enough" value. 186 #if defined(OS_MACOSX) 187 static const size_t kMaxReadFDBuffer = 1024; 188 #else 189 static const size_t kMaxReadFDBuffer = CMSG_SPACE(sizeof(int) * kMaxReadFDs); 190 #endif 191 192 // Temporary buffer used to receive the file descriptors from recvmsg. 193 // Code that writes into this should immediately read them out and save 194 // them to input_fds_, since this buffer will be re-used anytime we call 195 // recvmsg. 196 char input_cmsg_buf_[kMaxReadFDBuffer]; 197 198 // File descriptors extracted from messages coming off of the channel. The 199 // handles may span messages and come off different channels from the message 200 // data (in the case of READWRITE), and are processed in FIFO here. 201 // NOTE: The implementation assumes underlying storage here is contiguous, so 202 // don't change to something like std::deque<> without changing the 203 // implementation! 204 std::vector<int> input_fds_; 205 206 #if defined(OS_MACOSX) 207 // On OSX, sent FDs must not be closed until we get an ack. 208 // Keep track of sent FDs here to make sure the remote is not 209 // trying to bamboozle us. 210 std::set<int> fds_to_close_; 211 #endif 212 213 // True if we are responsible for unlinking the unix domain socket file. 214 bool must_unlink_; 215 216 #if defined(OS_LINUX) 217 // If non-zero, overrides the process ID sent in the hello message. 218 static int global_pid_; 219 #endif // OS_LINUX 220 221 DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelPosix); 222 }; 223 224 } // namespace IPC 225 226 #endif // IPC_IPC_CHANNEL_POSIX_H_ 227