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