blob: 08529932250ad04d0c0a3c9be42049fed7728d02 [file] [log] [blame]
[email protected]11307022012-01-25 23:53:061// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d4651ff2008-12-02 16:51:582// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]946d1b22009-07-22 23:57:215#include "ipc/ipc_channel_posix.h"
[email protected]d4651ff2008-12-02 16:51:586
[email protected]c3110742008-12-11 00:36:477#include <errno.h>
[email protected]fa95fc92008-12-08 18:10:148#include <fcntl.h>
[email protected]e45e6c02008-12-15 22:02:179#include <stddef.h>
[email protected]fa95fc92008-12-08 18:10:1410#include <sys/socket.h>
11#include <sys/stat.h>
[email protected]57999812013-02-24 05:40:5212#include <sys/types.h>
[email protected]3fcbd4b2012-06-05 01:54:4613#include <unistd.h>
[email protected]e45e6c02008-12-15 22:02:1714
[email protected]4af5ef42011-10-18 17:46:2215#if defined(OS_OPENBSD)
16#include <sys/uio.h>
17#endif
18
hidehiko853d6082014-11-05 23:51:5219#if !defined(OS_NACL_NONSFI)
hidehikoc2eec0d2014-10-24 03:49:2720#include <sys/un.h>
21#endif
22
[email protected]e8fce882009-01-20 22:02:5823#include <map>
[email protected]57999812013-02-24 05:40:5224#include <string>
[email protected]e8fce882009-01-20 22:02:5825
[email protected]df3c1ca12008-12-19 21:37:0126#include "base/command_line.h"
[email protected]57999812013-02-24 05:40:5227#include "base/files/file_path.h"
thestigc9e38a22014-09-13 01:02:1128#include "base/files/file_util.h"
[email protected]c62dd9d2011-09-21 18:05:4129#include "base/location.h"
[email protected]fa95fc92008-12-08 18:10:1430#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:1531#include "base/memory/scoped_ptr.h"
32#include "base/memory/singleton.h"
[email protected]2025d002012-11-14 20:54:3533#include "base/posix/eintr_wrapper.h"
[email protected]613eef62012-11-09 23:46:5434#include "base/posix/global_descriptors.h"
[email protected]e66ef602013-07-24 05:15:2435#include "base/process/process_handle.h"
[email protected]5c41e6e12012-03-17 02:20:4636#include "base/rand_util.h"
[email protected]7286e3fc2011-07-19 22:13:2437#include "base/stl_util.h"
[email protected]4aa794a12013-06-11 06:32:1838#include "base/strings/string_util.h"
[email protected]20305ec2011-01-21 04:55:5239#include "base/synchronization/lock.h"
[email protected]946d1b22009-07-22 23:57:2140#include "ipc/file_descriptor_set_posix.h"
[email protected]4e07f842012-11-15 22:22:1741#include "ipc/ipc_descriptors.h"
42#include "ipc/ipc_listener.h"
[email protected]946d1b22009-07-22 23:57:2143#include "ipc/ipc_logging.h"
44#include "ipc/ipc_message_utils.h"
[email protected]4e07f842012-11-15 22:22:1745#include "ipc/ipc_switches.h"
[email protected]bdf9bdc2013-03-13 04:23:1046#include "ipc/unix_domain_socket_util.h"
[email protected]d4651ff2008-12-02 16:51:5847
48namespace IPC {
49
[email protected]5f594c02009-05-01 22:37:5950// IPC channels on Windows use named pipes (CreateNamedPipe()) with
[email protected]22b42c52010-12-20 06:59:2351// channel ids as the pipe names. Channels on POSIX use sockets as
52// pipes These don't quite line up.
[email protected]5f594c02009-05-01 22:37:5953//
[email protected]22b42c52010-12-20 06:59:2354// When creating a child subprocess we use a socket pair and the parent side of
55// the fork arranges it such that the initial control channel ends up on the
[email protected]cc8f1462009-06-12 17:36:5556// magic file descriptor kPrimaryIPCChannel in the child. Future
[email protected]5f594c02009-05-01 22:37:5957// connections (file descriptors) can then be passed via that
58// connection via sendmsg().
[email protected]22b42c52010-12-20 06:59:2359//
60// A POSIX IPC channel can also be set up as a server for a bound UNIX domain
61// socket, and will handle multiple connect and disconnect sequences. Currently
62// it is limited to one connection at a time.
[email protected]5f594c02009-05-01 22:37:5963
[email protected]fa95fc92008-12-08 18:10:1464//------------------------------------------------------------------------------
[email protected]fa95fc92008-12-08 18:10:1465namespace {
66
[email protected]5f594c02009-05-01 22:37:5967// The PipeMap class works around this quirk related to unit tests:
[email protected]e8fce882009-01-20 22:02:5868//
[email protected]5f594c02009-05-01 22:37:5969// When running as a server, we install the client socket in a
[email protected]cc8f1462009-06-12 17:36:5570// specific file descriptor number (@kPrimaryIPCChannel). However, we
[email protected]5f594c02009-05-01 22:37:5971// also have to support the case where we are running unittests in the
72// same process. (We do not support forking without execing.)
[email protected]e8fce882009-01-20 22:02:5873//
74// Case 1: normal running
75// The IPC server object will install a mapping in PipeMap from the
76// name which it was given to the client pipe. When forking the client, the
77// GetClientFileDescriptorMapping will ensure that the socket is installed in
[email protected]cc8f1462009-06-12 17:36:5578// the magic slot (@kPrimaryIPCChannel). The client will search for the
[email protected]e8fce882009-01-20 22:02:5879// mapping, but it won't find any since we are in a new process. Thus the
80// magic fd number is returned. Once the client connects, the server will
[email protected]5f594c02009-05-01 22:37:5981// close its copy of the client socket and remove the mapping.
[email protected]e8fce882009-01-20 22:02:5882//
83// Case 2: unittests - client and server in the same process
84// The IPC server will install a mapping as before. The client will search
85// for a mapping and find out. It duplicates the file descriptor and
86// connects. Once the client connects, the server will close the original
87// copy of the client socket and remove the mapping. Thus, when the client
88// object closes, it will close the only remaining copy of the client socket
89// in the fd table and the server will see EOF on its side.
90//
91// TODO(port): a client process cannot connect to multiple IPC channels with
92// this scheme.
93
94class PipeMap {
95 public:
[email protected]864b5582010-12-04 23:00:1096 static PipeMap* GetInstance() {
97 return Singleton<PipeMap>::get();
98 }
99
[email protected]42ce94e2010-12-08 19:28:09100 ~PipeMap() {
101 // Shouldn't have left over pipes.
[email protected]f6b8ce32011-03-02 00:03:18102 DCHECK(map_.empty());
[email protected]42ce94e2010-12-08 19:28:09103 }
104
[email protected]e8fce882009-01-20 22:02:58105 // Lookup a given channel id. Return -1 if not found.
106 int Lookup(const std::string& channel_id) {
[email protected]20305ec2011-01-21 04:55:52107 base::AutoLock locked(lock_);
[email protected]e8fce882009-01-20 22:02:58108
109 ChannelToFDMap::const_iterator i = map_.find(channel_id);
110 if (i == map_.end())
111 return -1;
112 return i->second;
113 }
114
115 // Remove the mapping for the given channel id. No error is signaled if the
116 // channel_id doesn't exist
[email protected]2ce26c432011-09-19 17:08:12117 void Remove(const std::string& channel_id) {
[email protected]20305ec2011-01-21 04:55:52118 base::AutoLock locked(lock_);
[email protected]2ce26c432011-09-19 17:08:12119 map_.erase(channel_id);
[email protected]e8fce882009-01-20 22:02:58120 }
121
122 // Insert a mapping from @channel_id to @fd. It's a fatal error to insert a
123 // mapping if one already exists for the given channel_id
124 void Insert(const std::string& channel_id, int fd) {
[email protected]20305ec2011-01-21 04:55:52125 base::AutoLock locked(lock_);
[email protected]60ea6052011-04-18 20:07:08126 DCHECK_NE(-1, fd);
[email protected]e8fce882009-01-20 22:02:58127
128 ChannelToFDMap::const_iterator i = map_.find(channel_id);
[email protected]d2e884d2009-06-22 20:37:52129 CHECK(i == map_.end()) << "Creating second IPC server (fd " << fd << ") "
130 << "for '" << channel_id << "' while first "
131 << "(fd " << i->second << ") still exists";
[email protected]e8fce882009-01-20 22:02:58132 map_[channel_id] = fd;
133 }
134
135 private:
[email protected]20305ec2011-01-21 04:55:52136 base::Lock lock_;
[email protected]e8fce882009-01-20 22:02:58137 typedef std::map<std::string, int> ChannelToFDMap;
138 ChannelToFDMap map_;
[email protected]864b5582010-12-04 23:00:10139
140 friend struct DefaultSingletonTraits<PipeMap>;
[email protected]e097b932014-03-19 06:34:52141#if defined(OS_ANDROID)
142 friend void ::IPC::Channel::NotifyProcessForkedForTesting();
143#endif
[email protected]e8fce882009-01-20 22:02:58144};
145
[email protected]df3c1ca12008-12-19 21:37:01146//------------------------------------------------------------------------------
[email protected]fa95fc92008-12-08 18:10:14147
[email protected]86c3d9e2009-12-08 14:48:08148bool SocketWriteErrorIsRecoverable() {
149#if defined(OS_MACOSX)
150 // On OS X if sendmsg() is trying to send fds between processes and there
151 // isn't enough room in the output buffer to send the fd structure over
152 // atomically then EMSGSIZE is returned.
153 //
154 // EMSGSIZE presents a problem since the system APIs can only call us when
155 // there's room in the socket buffer and not when there is "enough" room.
156 //
157 // The current behavior is to return to the event loop when EMSGSIZE is
158 // received and hopefull service another FD. This is however still
159 // technically a busy wait since the event loop will call us right back until
160 // the receiver has read enough data to allow passing the FD over atomically.
161 return errno == EAGAIN || errno == EMSGSIZE;
162#else
163 return errno == EAGAIN;
[email protected]22b42c52010-12-20 06:59:23164#endif // OS_MACOSX
[email protected]86c3d9e2009-12-08 14:48:08165}
166
[email protected]fa95fc92008-12-08 18:10:14167} // namespace
[email protected]e097b932014-03-19 06:34:52168
169#if defined(OS_ANDROID)
170// When we fork for simple tests on Android, we can't 'exec', so we need to
171// reset these entries manually to get the expected testing behavior.
172void Channel::NotifyProcessForkedForTesting() {
173 PipeMap::GetInstance()->map_.clear();
174}
175#endif
176
[email protected]d4651ff2008-12-02 16:51:58177//------------------------------------------------------------------------------
178
perkjdbcac352014-12-11 17:27:58179#if defined(OS_LINUX)
180int ChannelPosix::global_pid_ = 0;
181#endif // OS_LINUX
182
[email protected]2f60c9b2014-06-06 20:13:51183ChannelPosix::ChannelPosix(const IPC::ChannelHandle& channel_handle,
184 Mode mode, Listener* listener)
[email protected]d805c6a2012-03-08 12:30:28185 : ChannelReader(listener),
186 mode_(mode),
[email protected]0a6fc4b2012-04-05 02:38:34187 peer_pid_(base::kNullProcessId),
[email protected]e45e6c02008-12-15 22:02:17188 is_blocked_on_write_(false),
[email protected]22b42c52010-12-20 06:59:23189 waiting_connect_(true),
[email protected]e45e6c02008-12-15 22:02:17190 message_send_bytes_written_(0),
[email protected]22b42c52010-12-20 06:59:23191 pipe_name_(channel_handle.name),
[email protected]bf84c582011-08-23 03:17:02192 must_unlink_(false) {
[email protected]df60edb2011-06-21 22:48:29193 memset(input_cmsg_buf_, 0, sizeof(input_cmsg_buf_));
[email protected]1707726c2011-02-03 20:35:09194 if (!CreatePipe(channel_handle)) {
[email protected]22b42c52010-12-20 06:59:23195 // The pipe may have been closed already.
[email protected]1707726c2011-02-03 20:35:09196 const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client";
[email protected]42ce94e2010-12-08 19:28:09197 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name
[email protected]22b42c52010-12-20 06:59:23198 << "\" in " << modestr << " mode";
[email protected]fa95fc92008-12-08 18:10:14199 }
[email protected]d4651ff2008-12-02 16:51:58200}
201
[email protected]2f60c9b2014-06-06 20:13:51202ChannelPosix::~ChannelPosix() {
[email protected]601858c02010-09-01 17:08:20203 Close();
204}
205
[email protected]d2e884d2009-06-22 20:37:52206bool SocketPair(int* fd1, int* fd2) {
207 int pipe_fds[2];
208 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) {
[email protected]57b765672009-10-13 18:27:40209 PLOG(ERROR) << "socketpair()";
[email protected]d2e884d2009-06-22 20:37:52210 return false;
211 }
212
213 // Set both ends to be non-blocking.
214 if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 ||
215 fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) {
[email protected]57b765672009-10-13 18:27:40216 PLOG(ERROR) << "fcntl(O_NONBLOCK)";
[email protected]d89eec82013-12-03 14:10:59217 if (IGNORE_EINTR(close(pipe_fds[0])) < 0)
[email protected]70eb6572010-06-23 00:37:46218 PLOG(ERROR) << "close";
[email protected]d89eec82013-12-03 14:10:59219 if (IGNORE_EINTR(close(pipe_fds[1])) < 0)
[email protected]70eb6572010-06-23 00:37:46220 PLOG(ERROR) << "close";
[email protected]d2e884d2009-06-22 20:37:52221 return false;
222 }
223
224 *fd1 = pipe_fds[0];
225 *fd2 = pipe_fds[1];
226
227 return true;
228}
229
[email protected]2f60c9b2014-06-06 20:13:51230bool ChannelPosix::CreatePipe(
[email protected]1707726c2011-02-03 20:35:09231 const IPC::ChannelHandle& channel_handle) {
morritace44fef2014-09-29 22:25:54232 DCHECK(!server_listen_pipe_.is_valid() && !pipe_.is_valid());
[email protected]22b42c52010-12-20 06:59:23233
234 // Four possible cases:
235 // 1) It's a channel wrapping a pipe that is given to us.
236 // 2) It's for a named channel, so we create it.
237 // 3) It's for a client that we implement ourself. This is used
[email protected]e097b932014-03-19 06:34:52238 // in single-process unittesting.
[email protected]22b42c52010-12-20 06:59:23239 // 4) It's the initial IPC channel:
240 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set.
241 // 4b) Server side: create the pipe.
242
morritace44fef2014-09-29 22:25:54243 base::ScopedFD local_pipe;
[email protected]22b42c52010-12-20 06:59:23244 if (channel_handle.socket.fd != -1) {
245 // Case 1 from comment above.
morritace44fef2014-09-29 22:25:54246 local_pipe.reset(channel_handle.socket.fd);
[email protected]22b42c52010-12-20 06:59:23247#if defined(IPC_USES_READWRITE)
248 // Test the socket passed into us to make sure it is nonblocking.
249 // We don't want to call read/write on a blocking socket.
morritace44fef2014-09-29 22:25:54250 int value = fcntl(local_pipe.get(), F_GETFL);
[email protected]22b42c52010-12-20 06:59:23251 if (value == -1) {
252 PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_;
253 return false;
254 }
255 if (!(value & O_NONBLOCK)) {
256 LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK";
257 return false;
258 }
259#endif // IPC_USES_READWRITE
[email protected]1707726c2011-02-03 20:35:09260 } else if (mode_ & MODE_NAMED_FLAG) {
hidehiko853d6082014-11-05 23:51:52261#if defined(OS_NACL_NONSFI)
hidehikoc2eec0d2014-10-24 03:49:27262 LOG(FATAL)
263 << "IPC channels in nacl_helper_nonsfi should not be in NAMED mode.";
264#else
[email protected]22b42c52010-12-20 06:59:23265 // Case 2 from comment above.
morritace44fef2014-09-29 22:25:54266 int local_pipe_fd = -1;
267
[email protected]1707726c2011-02-03 20:35:09268 if (mode_ & MODE_SERVER_FLAG) {
[email protected]bdf9bdc2013-03-13 04:23:10269 if (!CreateServerUnixDomainSocket(base::FilePath(pipe_name_),
morritace44fef2014-09-29 22:25:54270 &local_pipe_fd)) {
[email protected]df3c1ca12008-12-19 21:37:01271 return false;
272 }
morritace44fef2014-09-29 22:25:54273
[email protected]56f0f262011-02-24 17:14:36274 must_unlink_ = true;
[email protected]1707726c2011-02-03 20:35:09275 } else if (mode_ & MODE_CLIENT_FLAG) {
[email protected]bdf9bdc2013-03-13 04:23:10276 if (!CreateClientUnixDomainSocket(base::FilePath(pipe_name_),
morritace44fef2014-09-29 22:25:54277 &local_pipe_fd)) {
[email protected]df3c1ca12008-12-19 21:37:01278 return false;
279 }
[email protected]1707726c2011-02-03 20:35:09280 } else {
[email protected]6aad23f92011-03-02 22:27:14281 LOG(ERROR) << "Bad mode: " << mode_;
[email protected]1707726c2011-02-03 20:35:09282 return false;
[email protected]fa95fc92008-12-08 18:10:14283 }
morritace44fef2014-09-29 22:25:54284
285 local_pipe.reset(local_pipe_fd);
hidehiko853d6082014-11-05 23:51:52286#endif // !defined(OS_NACL_NONSFI)
[email protected]fa95fc92008-12-08 18:10:14287 } else {
morritace44fef2014-09-29 22:25:54288 local_pipe.reset(PipeMap::GetInstance()->Lookup(pipe_name_));
[email protected]1707726c2011-02-03 20:35:09289 if (mode_ & MODE_CLIENT_FLAG) {
morritace44fef2014-09-29 22:25:54290 if (local_pipe.is_valid()) {
[email protected]22b42c52010-12-20 06:59:23291 // Case 3 from comment above.
292 // We only allow one connection.
morritace44fef2014-09-29 22:25:54293 local_pipe.reset(HANDLE_EINTR(dup(local_pipe.release())));
[email protected]2ce26c432011-09-19 17:08:12294 PipeMap::GetInstance()->Remove(pipe_name_);
[email protected]d2e884d2009-06-22 20:37:52295 } else {
[email protected]22b42c52010-12-20 06:59:23296 // Case 4a from comment above.
[email protected]554a8852009-11-30 22:14:37297 // Guard against inappropriate reuse of the initial IPC channel. If
298 // an IPC channel closes and someone attempts to reuse it by name, the
299 // initial channel must not be recycled here. http://crbug.com/26754.
300 static bool used_initial_channel = false;
301 if (used_initial_channel) {
[email protected]9f816f72010-03-16 20:31:10302 LOG(FATAL) << "Denying attempt to reuse initial IPC channel for "
303 << pipe_name_;
[email protected]554a8852009-11-30 22:14:37304 return false;
305 }
306 used_initial_channel = true;
307
morritace44fef2014-09-29 22:25:54308 local_pipe.reset(
309 base::GlobalDescriptors::GetInstance()->Get(kPrimaryIPCChannel));
[email protected]df3c1ca12008-12-19 21:37:01310 }
[email protected]1707726c2011-02-03 20:35:09311 } else if (mode_ & MODE_SERVER_FLAG) {
[email protected]22b42c52010-12-20 06:59:23312 // Case 4b from comment above.
morritace44fef2014-09-29 22:25:54313 if (local_pipe.is_valid()) {
[email protected]22b42c52010-12-20 06:59:23314 LOG(ERROR) << "Server already exists for " << pipe_name_;
morritace44fef2014-09-29 22:25:54315 // This is a client side pipe registered by other server and
316 // shouldn't be closed.
317 ignore_result(local_pipe.release());
[email protected]baf556a2009-09-04 21:34:05318 return false;
319 }
[email protected]2ce26c432011-09-19 17:08:12320 base::AutoLock lock(client_pipe_lock_);
morritace44fef2014-09-29 22:25:54321 int local_pipe_fd = -1, client_pipe_fd = -1;
322 if (!SocketPair(&local_pipe_fd, &client_pipe_fd))
[email protected]22b42c52010-12-20 06:59:23323 return false;
morritace44fef2014-09-29 22:25:54324 local_pipe.reset(local_pipe_fd);
325 client_pipe_.reset(client_pipe_fd);
326 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_fd);
[email protected]22b42c52010-12-20 06:59:23327 } else {
[email protected]6aad23f92011-03-02 22:27:14328 LOG(ERROR) << "Bad mode: " << mode_;
[email protected]22b42c52010-12-20 06:59:23329 return false;
[email protected]baf556a2009-09-04 21:34:05330 }
331 }
[email protected]22b42c52010-12-20 06:59:23332
[email protected]22b42c52010-12-20 06:59:23333#if defined(IPC_USES_READWRITE)
334 // Create a dedicated socketpair() for exchanging file descriptors.
335 // See comments for IPC_USES_READWRITE for details.
[email protected]1707726c2011-02-03 20:35:09336 if (mode_ & MODE_CLIENT_FLAG) {
morritace44fef2014-09-29 22:25:54337 int fd_pipe_fd = 1, remote_fd_pipe_fd = -1;
338 if (!SocketPair(&fd_pipe_fd, &remote_fd_pipe_fd)) {
[email protected]22b42c52010-12-20 06:59:23339 return false;
340 }
morritace44fef2014-09-29 22:25:54341
342 fd_pipe_.reset(fd_pipe_fd);
343 remote_fd_pipe_.reset(remote_fd_pipe_fd);
[email protected]22b42c52010-12-20 06:59:23344 }
345#endif // IPC_USES_READWRITE
346
hidehikoc2eec0d2014-10-24 03:49:27347 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) {
hidehiko853d6082014-11-05 23:51:52348#if defined(OS_NACL_NONSFI)
hidehikoc2eec0d2014-10-24 03:49:27349 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi "
350 << "should not be in NAMED or SERVER mode.";
351#else
morritace44fef2014-09-29 22:25:54352 server_listen_pipe_.reset(local_pipe.release());
hidehikoc2eec0d2014-10-24 03:49:27353#endif
354 } else {
morritace44fef2014-09-29 22:25:54355 pipe_.reset(local_pipe.release());
hidehikoc2eec0d2014-10-24 03:49:27356 }
[email protected]fa95fc92008-12-08 18:10:14357 return true;
[email protected]d4651ff2008-12-02 16:51:58358}
359
[email protected]2f60c9b2014-06-06 20:13:51360bool ChannelPosix::Connect() {
morritace44fef2014-09-29 22:25:54361 if (!server_listen_pipe_.is_valid() && !pipe_.is_valid()) {
[email protected]0e8a7912014-02-21 00:18:29362 DLOG(WARNING) << "Channel creation failed: " << pipe_name_;
[email protected]22b42c52010-12-20 06:59:23363 return false;
364 }
365
366 bool did_connect = true;
morritace44fef2014-09-29 22:25:54367 if (server_listen_pipe_.is_valid()) {
hidehiko853d6082014-11-05 23:51:52368#if defined(OS_NACL_NONSFI)
hidehikoc2eec0d2014-10-24 03:49:27369 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi "
370 << "should always be in client mode.";
371#else
[email protected]22b42c52010-12-20 06:59:23372 // Watch the pipe for connections, and turn any connections into
373 // active sockets.
[email protected]fd0a773a2013-04-30 20:55:03374 base::MessageLoopForIO::current()->WatchFileDescriptor(
morritace44fef2014-09-29 22:25:54375 server_listen_pipe_.get(),
[email protected]e45e6c02008-12-15 22:02:17376 true,
[email protected]fd0a773a2013-04-30 20:55:03377 base::MessageLoopForIO::WATCH_READ,
[email protected]e45e6c02008-12-15 22:02:17378 &server_listen_connection_watcher_,
379 this);
hidehikoc2eec0d2014-10-24 03:49:27380#endif
[email protected]fa95fc92008-12-08 18:10:14381 } else {
[email protected]22b42c52010-12-20 06:59:23382 did_connect = AcceptConnection();
[email protected]fa95fc92008-12-08 18:10:14383 }
[email protected]22b42c52010-12-20 06:59:23384 return did_connect;
[email protected]d4651ff2008-12-02 16:51:58385}
[email protected]fa95fc92008-12-08 18:10:14386
[email protected]2f60c9b2014-06-06 20:13:51387void ChannelPosix::CloseFileDescriptors(Message* msg) {
[email protected]dc875dc2013-10-15 00:07:00388#if defined(OS_MACOSX)
389 // There is a bug on OSX which makes it dangerous to close
390 // a file descriptor while it is in transit. So instead we
391 // store the file descriptor in a set and send a message to
392 // the recipient, which is queued AFTER the message that
393 // sent the FD. The recipient will reply to the message,
394 // letting us know that it is now safe to close the file
395 // descriptor. For more information, see:
396 // http://crbug.com/298276
397 std::vector<int> to_close;
398 msg->file_descriptor_set()->ReleaseFDsToClose(&to_close);
399 for (size_t i = 0; i < to_close.size(); i++) {
400 fds_to_close_.insert(to_close[i]);
401 QueueCloseFDMessage(to_close[i], 2);
402 }
403#else
404 msg->file_descriptor_set()->CommitAll();
405#endif
406}
407
[email protected]2f60c9b2014-06-06 20:13:51408bool ChannelPosix::ProcessOutgoingMessages() {
[email protected]fa95fc92008-12-08 18:10:14409 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
410 // no connection?
[email protected]22b42c52010-12-20 06:59:23411 if (output_queue_.empty())
[email protected]c7f91e82010-12-20 06:39:44412 return true;
[email protected]c7f91e82010-12-20 06:39:44413
morritace44fef2014-09-29 22:25:54414 if (!pipe_.is_valid())
[email protected]fa95fc92008-12-08 18:10:14415 return false;
416
[email protected]fa95fc92008-12-08 18:10:14417 // Write out all the messages we can till the write blocks or there are no
418 // more outgoing messages.
419 while (!output_queue_.empty()) {
420 Message* msg = output_queue_.front();
421
422 size_t amt_to_write = msg->size() - message_send_bytes_written_;
[email protected]60ea6052011-04-18 20:07:08423 DCHECK_NE(0U, amt_to_write);
[email protected]baf556a2009-09-04 21:34:05424 const char* out_bytes = reinterpret_cast<const char*>(msg->data()) +
[email protected]fa95fc92008-12-08 18:10:14425 message_send_bytes_written_;
[email protected]526776c2009-02-07 00:39:26426
[email protected]157c61b2009-05-01 21:37:31427 struct msghdr msgh = {0};
428 struct iovec iov = {const_cast<char*>(out_bytes), amt_to_write};
429 msgh.msg_iov = &iov;
430 msgh.msg_iovlen = 1;
431 char buf[CMSG_SPACE(
[email protected]05094a32011-09-01 00:50:13432 sizeof(int) * FileDescriptorSet::kMaxDescriptorsPerMessage)];
[email protected]526776c2009-02-07 00:39:26433
[email protected]baf556a2009-09-04 21:34:05434 ssize_t bytes_written = 1;
435 int fd_written = -1;
436
[email protected]157c61b2009-05-01 21:37:31437 if (message_send_bytes_written_ == 0 &&
438 !msg->file_descriptor_set()->empty()) {
439 // This is the first chunk of a message which has descriptors to send
440 struct cmsghdr *cmsg;
441 const unsigned num_fds = msg->file_descriptor_set()->size();
[email protected]526776c2009-02-07 00:39:26442
[email protected]05094a32011-09-01 00:50:13443 DCHECK(num_fds <= FileDescriptorSet::kMaxDescriptorsPerMessage);
[email protected]aac449e2010-06-10 21:39:04444 if (msg->file_descriptor_set()->ContainsDirectoryDescriptor()) {
445 LOG(FATAL) << "Panic: attempting to transport directory descriptor over"
446 " IPC. Aborting to maintain sandbox isolation.";
447 // If you have hit this then something tried to send a file descriptor
448 // to a directory over an IPC channel. Since IPC channels span
449 // sandboxes this is very bad: the receiving process can use openat
450 // with ".." elements in the path in order to reach the real
451 // filesystem.
452 }
[email protected]526776c2009-02-07 00:39:26453
[email protected]157c61b2009-05-01 21:37:31454 msgh.msg_control = buf;
455 msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
456 cmsg = CMSG_FIRSTHDR(&msgh);
457 cmsg->cmsg_level = SOL_SOCKET;
458 cmsg->cmsg_type = SCM_RIGHTS;
459 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
morrita96693852014-09-24 20:11:45460 msg->file_descriptor_set()->PeekDescriptors(
[email protected]157c61b2009-05-01 21:37:31461 reinterpret_cast<int*>(CMSG_DATA(cmsg)));
462 msgh.msg_controllen = cmsg->cmsg_len;
[email protected]526776c2009-02-07 00:39:26463
[email protected]168ae922009-12-04 18:08:45464 // DCHECK_LE above already checks that
[email protected]05094a32011-09-01 00:50:13465 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow.
[email protected]168ae922009-12-04 18:08:45466 msg->header()->num_fds = static_cast<uint16>(num_fds);
[email protected]baf556a2009-09-04 21:34:05467
[email protected]e40f5a0b2010-12-08 21:22:24468#if defined(IPC_USES_READWRITE)
[email protected]d805c6a2012-03-08 12:30:28469 if (!IsHelloMessage(*msg)) {
[email protected]baf556a2009-09-04 21:34:05470 // Only the Hello message sends the file descriptor with the message.
471 // Subsequently, we can send file descriptors on the dedicated
472 // fd_pipe_ which makes Seccomp sandbox operation more efficient.
473 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 };
474 msgh.msg_iov = &fd_pipe_iov;
morritace44fef2014-09-29 22:25:54475 fd_written = fd_pipe_.get();
476 bytes_written =
477 HANDLE_EINTR(sendmsg(fd_pipe_.get(), &msgh, MSG_DONTWAIT));
[email protected]baf556a2009-09-04 21:34:05478 msgh.msg_iov = &iov;
479 msgh.msg_controllen = 0;
480 if (bytes_written > 0) {
[email protected]dc875dc2013-10-15 00:07:00481 CloseFileDescriptors(msg);
[email protected]baf556a2009-09-04 21:34:05482 }
483 }
[email protected]22b42c52010-12-20 06:59:23484#endif // IPC_USES_READWRITE
[email protected]157c61b2009-05-01 21:37:31485 }
486
[email protected]baf556a2009-09-04 21:34:05487 if (bytes_written == 1) {
morritace44fef2014-09-29 22:25:54488 fd_written = pipe_.get();
[email protected]e40f5a0b2010-12-08 21:22:24489#if defined(IPC_USES_READWRITE)
[email protected]d805c6a2012-03-08 12:30:28490 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) {
[email protected]7ee1a44c2010-07-23 14:18:59491 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
[email protected]baf556a2009-09-04 21:34:05492 }
[email protected]22b42c52010-12-20 06:59:23493 if (!msgh.msg_controllen) {
morritace44fef2014-09-29 22:25:54494 bytes_written =
495 HANDLE_EINTR(write(pipe_.get(), out_bytes, amt_to_write));
[email protected]baf556a2009-09-04 21:34:05496 } else
[email protected]22b42c52010-12-20 06:59:23497#endif // IPC_USES_READWRITE
[email protected]baf556a2009-09-04 21:34:05498 {
morritace44fef2014-09-29 22:25:54499 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT));
[email protected]baf556a2009-09-04 21:34:05500 }
501 }
[email protected]157c61b2009-05-01 21:37:31502 if (bytes_written > 0)
[email protected]dc875dc2013-10-15 00:07:00503 CloseFileDescriptors(msg);
[email protected]fa95fc92008-12-08 18:10:14504
[email protected]86c3d9e2009-12-08 14:48:08505 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) {
[email protected]0e8a7912014-02-21 00:18:29506 // We can't close the pipe here, because calling OnChannelError
507 // may destroy this object, and that would be bad if we are
508 // called from Send(). Instead, we return false and hope the
509 // caller will close the pipe. If they do not, the pipe will
510 // still be closed next time OnFileCanReadWithoutBlocking is
511 // called.
[email protected]cb38c0b22009-05-27 18:29:48512#if defined(OS_MACOSX)
513 // On OSX writing to a pipe with no listener returns EPERM.
514 if (errno == EPERM) {
[email protected]cb38c0b22009-05-27 18:29:48515 return false;
516 }
517#endif // OS_MACOSX
[email protected]7bf54f5e2009-10-23 01:48:21518 if (errno == EPIPE) {
[email protected]7bf54f5e2009-10-23 01:48:21519 return false;
520 }
[email protected]780ae942009-12-03 13:35:46521 PLOG(ERROR) << "pipe error on "
522 << fd_written
[email protected]9fbc2f2f2011-02-11 08:43:52523 << " Currently writing message of size: "
[email protected]86c3d9e2009-12-08 14:48:08524 << msg->size();
[email protected]fa95fc92008-12-08 18:10:14525 return false;
526 }
527
528 if (static_cast<size_t>(bytes_written) != amt_to_write) {
[email protected]3d1b6662009-01-29 17:03:11529 if (bytes_written > 0) {
530 // If write() fails with EAGAIN then bytes_written will be -1.
531 message_send_bytes_written_ += bytes_written;
532 }
[email protected]fa95fc92008-12-08 18:10:14533
534 // Tell libevent to call us back once things are unblocked.
[email protected]e45e6c02008-12-15 22:02:17535 is_blocked_on_write_ = true;
[email protected]fd0a773a2013-04-30 20:55:03536 base::MessageLoopForIO::current()->WatchFileDescriptor(
morritace44fef2014-09-29 22:25:54537 pipe_.get(),
[email protected]e45e6c02008-12-15 22:02:17538 false, // One shot
[email protected]fd0a773a2013-04-30 20:55:03539 base::MessageLoopForIO::WATCH_WRITE,
[email protected]e45e6c02008-12-15 22:02:17540 &write_watcher_,
541 this);
[email protected]3d1b6662009-01-29 17:03:11542 return true;
[email protected]fa95fc92008-12-08 18:10:14543 } else {
544 message_send_bytes_written_ = 0;
545
546 // Message sent OK!
[email protected]2a9d601b2010-10-19 23:50:00547 DVLOG(2) << "sent message @" << msg << " on channel @" << this
morritace44fef2014-09-29 22:25:54548 << " with type " << msg->type() << " on fd " << pipe_.get();
[email protected]baf556a2009-09-04 21:34:05549 delete output_queue_.front();
[email protected]fa95fc92008-12-08 18:10:14550 output_queue_.pop();
[email protected]fa95fc92008-12-08 18:10:14551 }
552 }
553 return true;
554}
555
[email protected]2f60c9b2014-06-06 20:13:51556bool ChannelPosix::Send(Message* message) {
[email protected]2a9d601b2010-10-19 23:50:00557 DVLOG(2) << "sending message @" << message << " on channel @" << this
558 << " with type " << message->type()
559 << " (" << output_queue_.size() << " in queue)";
[email protected]fa95fc92008-12-08 18:10:14560
[email protected]4c2c1db2009-03-20 20:56:55561#ifdef IPC_MESSAGE_LOG_ENABLED
[email protected]8e8bb6d2010-12-13 08:18:55562 Logging::GetInstance()->OnSendMessage(message, "");
[email protected]22b42c52010-12-20 06:59:23563#endif // IPC_MESSAGE_LOG_ENABLED
[email protected]fa95fc92008-12-08 18:10:14564
[email protected]2c391df2012-09-18 03:41:29565 message->TraceMessageBegin();
[email protected]fa95fc92008-12-08 18:10:14566 output_queue_.push(message);
[email protected]22b42c52010-12-20 06:59:23567 if (!is_blocked_on_write_ && !waiting_connect_) {
[email protected]13ffc272014-02-18 17:42:20568 return ProcessOutgoingMessages();
[email protected]fa95fc92008-12-08 18:10:14569 }
570
571 return true;
572}
573
[email protected]2f60c9b2014-06-06 20:13:51574int ChannelPosix::GetClientFileDescriptor() const {
[email protected]2ce26c432011-09-19 17:08:12575 base::AutoLock lock(client_pipe_lock_);
morritace44fef2014-09-29 22:25:54576 return client_pipe_.get();
[email protected]df3c1ca12008-12-19 21:37:01577}
578
morritaa409ccc2014-10-20 23:53:25579base::ScopedFD ChannelPosix::TakeClientFileDescriptor() {
[email protected]2ce26c432011-09-19 17:08:12580 base::AutoLock lock(client_pipe_lock_);
morritace44fef2014-09-29 22:25:54581 if (!client_pipe_.is_valid())
morritaa409ccc2014-10-20 23:53:25582 return base::ScopedFD();
morritace44fef2014-09-29 22:25:54583 PipeMap::GetInstance()->Remove(pipe_name_);
morritaa409ccc2014-10-20 23:53:25584 return client_pipe_.Pass();
[email protected]2ce26c432011-09-19 17:08:12585}
586
[email protected]2f60c9b2014-06-06 20:13:51587void ChannelPosix::CloseClientFileDescriptor() {
[email protected]2ce26c432011-09-19 17:08:12588 base::AutoLock lock(client_pipe_lock_);
morritace44fef2014-09-29 22:25:54589 if (!client_pipe_.is_valid())
590 return;
591 PipeMap::GetInstance()->Remove(pipe_name_);
592 client_pipe_.reset();
[email protected]2ce26c432011-09-19 17:08:12593}
594
[email protected]2f60c9b2014-06-06 20:13:51595bool ChannelPosix::AcceptsConnections() const {
morritace44fef2014-09-29 22:25:54596 return server_listen_pipe_.is_valid();
[email protected]22b42c52010-12-20 06:59:23597}
[email protected]9a44a4db62010-12-20 06:19:07598
[email protected]2f60c9b2014-06-06 20:13:51599bool ChannelPosix::HasAcceptedConnection() const {
morritace44fef2014-09-29 22:25:54600 return AcceptsConnections() && pipe_.is_valid();
[email protected]22b42c52010-12-20 06:59:23601}
[email protected]9a44a4db62010-12-20 06:19:07602
hidehiko853d6082014-11-05 23:51:52603#if !defined(OS_NACL_NONSFI)
hidehikoc2eec0d2014-10-24 03:49:27604// GetPeerEuid is not supported in nacl_helper_nonsfi.
[email protected]2f60c9b2014-06-06 20:13:51605bool ChannelPosix::GetPeerEuid(uid_t* peer_euid) const {
[email protected]bdf9bdc2013-03-13 04:23:10606 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection());
morritace44fef2014-09-29 22:25:54607 return IPC::GetPeerEuid(pipe_.get(), peer_euid);
[email protected]8ec3fbe2011-04-06 12:01:44608}
hidehikoc2eec0d2014-10-24 03:49:27609#endif
[email protected]8ec3fbe2011-04-06 12:01:44610
[email protected]2f60c9b2014-06-06 20:13:51611void ChannelPosix::ResetToAcceptingConnectionState() {
[email protected]22b42c52010-12-20 06:59:23612 // Unregister libevent for the unix domain socket and close it.
613 read_watcher_.StopWatchingFileDescriptor();
614 write_watcher_.StopWatchingFileDescriptor();
morritace44fef2014-09-29 22:25:54615 pipe_.reset();
[email protected]22b42c52010-12-20 06:59:23616#if defined(IPC_USES_READWRITE)
morritace44fef2014-09-29 22:25:54617 fd_pipe_.reset();
618 remote_fd_pipe_.reset();
[email protected]22b42c52010-12-20 06:59:23619#endif // IPC_USES_READWRITE
[email protected]c7f91e82010-12-20 06:39:44620
[email protected]22b42c52010-12-20 06:59:23621 while (!output_queue_.empty()) {
622 Message* m = output_queue_.front();
623 output_queue_.pop();
624 delete m;
[email protected]c7f91e82010-12-20 06:39:44625 }
626
[email protected]22b42c52010-12-20 06:59:23627 // Close any outstanding, received file descriptors.
[email protected]334f3022012-02-29 22:48:14628 ClearInputFDs();
[email protected]dc875dc2013-10-15 00:07:00629
630#if defined(OS_MACOSX)
631 // Clear any outstanding, sent file descriptors.
632 for (std::set<int>::iterator i = fds_to_close_.begin();
633 i != fds_to_close_.end();
634 ++i) {
[email protected]d89eec82013-12-03 14:10:59635 if (IGNORE_EINTR(close(*i)) < 0)
[email protected]dc875dc2013-10-15 00:07:00636 PLOG(ERROR) << "close";
637 }
638 fds_to_close_.clear();
639#endif
[email protected]22b42c52010-12-20 06:59:23640}
641
[email protected]313c00e52011-08-09 06:46:06642// static
[email protected]2f60c9b2014-06-06 20:13:51643bool ChannelPosix::IsNamedServerInitialized(
[email protected]313c00e52011-08-09 06:46:06644 const std::string& channel_id) {
[email protected]7567484142013-07-11 17:36:07645 return base::PathExists(base::FilePath(channel_id));
[email protected]313c00e52011-08-09 06:46:06646}
647
perkjdbcac352014-12-11 17:27:58648#if defined(OS_LINUX)
649// static
650void ChannelPosix::SetGlobalPid(int pid) {
651 global_pid_ = pid;
652}
653#endif // OS_LINUX
654
[email protected]22b42c52010-12-20 06:59:23655// Called by libevent when we can read from the pipe without blocking.
[email protected]2f60c9b2014-06-06 20:13:51656void ChannelPosix::OnFileCanReadWithoutBlocking(int fd) {
morritace44fef2014-09-29 22:25:54657 if (fd == server_listen_pipe_.get()) {
hidehiko853d6082014-11-05 23:51:52658#if defined(OS_NACL_NONSFI)
hidehikoc2eec0d2014-10-24 03:49:27659 LOG(FATAL)
660 << "IPC channels in nacl_helper_nonsfi should not be SERVER mode.";
661#else
[email protected]22b42c52010-12-20 06:59:23662 int new_pipe = 0;
morritace44fef2014-09-29 22:25:54663 if (!ServerAcceptConnection(server_listen_pipe_.get(), &new_pipe) ||
[email protected]bdf9bdc2013-03-13 04:23:10664 new_pipe < 0) {
[email protected]c7f91e82010-12-20 06:39:44665 Close();
[email protected]d805c6a2012-03-08 12:30:28666 listener()->OnChannelListenError();
[email protected]22b42c52010-12-20 06:59:23667 }
668
morritace44fef2014-09-29 22:25:54669 if (pipe_.is_valid()) {
[email protected]22b42c52010-12-20 06:59:23670 // We already have a connection. We only handle one at a time.
671 // close our new descriptor.
672 if (HANDLE_EINTR(shutdown(new_pipe, SHUT_RDWR)) < 0)
[email protected]334f3022012-02-29 22:48:14673 DPLOG(ERROR) << "shutdown " << pipe_name_;
[email protected]d89eec82013-12-03 14:10:59674 if (IGNORE_EINTR(close(new_pipe)) < 0)
[email protected]334f3022012-02-29 22:48:14675 DPLOG(ERROR) << "close " << pipe_name_;
[email protected]d805c6a2012-03-08 12:30:28676 listener()->OnChannelDenied();
[email protected]c7f91e82010-12-20 06:39:44677 return;
[email protected]9a44a4db62010-12-20 06:19:07678 }
morritace44fef2014-09-29 22:25:54679 pipe_.reset(new_pipe);
[email protected]22b42c52010-12-20 06:59:23680
[email protected]8ec3fbe2011-04-06 12:01:44681 if ((mode_ & MODE_OPEN_ACCESS_FLAG) == 0) {
682 // Verify that the IPC channel peer is running as the same user.
683 uid_t client_euid;
[email protected]bdf9bdc2013-03-13 04:23:10684 if (!GetPeerEuid(&client_euid)) {
[email protected]334f3022012-02-29 22:48:14685 DLOG(ERROR) << "Unable to query client euid";
[email protected]8ec3fbe2011-04-06 12:01:44686 ResetToAcceptingConnectionState();
687 return;
688 }
689 if (client_euid != geteuid()) {
[email protected]334f3022012-02-29 22:48:14690 DLOG(WARNING) << "Client euid is not authorised";
[email protected]8ec3fbe2011-04-06 12:01:44691 ResetToAcceptingConnectionState();
692 return;
693 }
694 }
695
[email protected]22b42c52010-12-20 06:59:23696 if (!AcceptConnection()) {
697 NOTREACHED() << "AcceptConnection should not fail on server";
698 }
[email protected]22b42c52010-12-20 06:59:23699 waiting_connect_ = false;
hidehikoc2eec0d2014-10-24 03:49:27700#endif
[email protected]22b42c52010-12-20 06:59:23701 } else if (fd == pipe_) {
[email protected]1707726c2011-02-03 20:35:09702 if (waiting_connect_ && (mode_ & MODE_SERVER_FLAG)) {
[email protected]22b42c52010-12-20 06:59:23703 waiting_connect_ = false;
704 }
705 if (!ProcessIncomingMessages()) {
[email protected]887250a2011-02-28 20:30:47706 // ClosePipeOnError may delete this object, so we mustn't call
707 // ProcessOutgoingMessages.
[email protected]22b42c52010-12-20 06:59:23708 ClosePipeOnError();
[email protected]dc875dc2013-10-15 00:07:00709 return;
[email protected]22b42c52010-12-20 06:59:23710 }
711 } else {
712 NOTREACHED() << "Unknown pipe " << fd;
[email protected]fa95fc92008-12-08 18:10:14713 }
714
715 // If we're a server and handshaking, then we want to make sure that we
716 // only send our handshake message after we've processed the client's.
717 // This gives us a chance to kill the client if the incoming handshake
[email protected]0e8a7912014-02-21 00:18:29718 // is invalid. This also flushes any closefd messages.
[email protected]dc875dc2013-10-15 00:07:00719 if (!is_blocked_on_write_) {
720 if (!ProcessOutgoingMessages()) {
721 ClosePipeOnError();
722 }
[email protected]fa95fc92008-12-08 18:10:14723 }
724}
725
726// Called by libevent when we can write to the pipe without blocking.
[email protected]2f60c9b2014-06-06 20:13:51727void ChannelPosix::OnFileCanWriteWithoutBlocking(int fd) {
morritace44fef2014-09-29 22:25:54728 DCHECK_EQ(pipe_.get(), fd);
[email protected]22b42c52010-12-20 06:59:23729 is_blocked_on_write_ = false;
[email protected]fa95fc92008-12-08 18:10:14730 if (!ProcessOutgoingMessages()) {
[email protected]22b42c52010-12-20 06:59:23731 ClosePipeOnError();
[email protected]9a44a4db62010-12-20 06:19:07732 }
733}
734
[email protected]2f60c9b2014-06-06 20:13:51735bool ChannelPosix::AcceptConnection() {
[email protected]fd0a773a2013-04-30 20:55:03736 base::MessageLoopForIO::current()->WatchFileDescriptor(
morritace44fef2014-09-29 22:25:54737 pipe_.get(),
738 true,
739 base::MessageLoopForIO::WATCH_READ,
740 &read_watcher_,
741 this);
[email protected]22b42c52010-12-20 06:59:23742 QueueHelloMessage();
743
[email protected]1707726c2011-02-03 20:35:09744 if (mode_ & MODE_CLIENT_FLAG) {
[email protected]22b42c52010-12-20 06:59:23745 // If we are a client we want to send a hello message out immediately.
746 // In server mode we will send a hello message when we receive one from a
747 // client.
748 waiting_connect_ = false;
[email protected]13ffc272014-02-18 17:42:20749 return ProcessOutgoingMessages();
[email protected]1707726c2011-02-03 20:35:09750 } else if (mode_ & MODE_SERVER_FLAG) {
[email protected]22b42c52010-12-20 06:59:23751 waiting_connect_ = true;
752 return true;
[email protected]1707726c2011-02-03 20:35:09753 } else {
754 NOTREACHED();
755 return false;
[email protected]22b42c52010-12-20 06:59:23756 }
757}
758
[email protected]2f60c9b2014-06-06 20:13:51759void ChannelPosix::ClosePipeOnError() {
[email protected]22b42c52010-12-20 06:59:23760 if (HasAcceptedConnection()) {
761 ResetToAcceptingConnectionState();
[email protected]d805c6a2012-03-08 12:30:28762 listener()->OnChannelError();
[email protected]22b42c52010-12-20 06:59:23763 } else {
764 Close();
765 if (AcceptsConnections()) {
[email protected]d805c6a2012-03-08 12:30:28766 listener()->OnChannelListenError();
[email protected]22b42c52010-12-20 06:59:23767 } else {
[email protected]d805c6a2012-03-08 12:30:28768 listener()->OnChannelError();
[email protected]22b42c52010-12-20 06:59:23769 }
770 }
771}
772
[email protected]64860882014-08-04 23:44:17773int ChannelPosix::GetHelloMessageProcId() const {
perkjdbcac352014-12-11 17:27:58774 int pid = base::GetCurrentProcId();
775#if defined(OS_LINUX)
776 // Our process may be in a sandbox with a separate PID namespace.
777 if (global_pid_) {
778 pid = global_pid_;
779 }
[email protected]e1d67a882011-08-31 21:11:04780#endif
perkjdbcac352014-12-11 17:27:58781 return pid;
[email protected]e1d67a882011-08-31 21:11:04782}
783
[email protected]2f60c9b2014-06-06 20:13:51784void ChannelPosix::QueueHelloMessage() {
[email protected]22b42c52010-12-20 06:59:23785 // Create the Hello message
786 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
[email protected]753bb252013-11-04 22:28:12787 HELLO_MESSAGE_TYPE,
788 IPC::Message::PRIORITY_NORMAL));
[email protected]e1d67a882011-08-31 21:11:04789 if (!msg->WriteInt(GetHelloMessageProcId())) {
[email protected]22b42c52010-12-20 06:59:23790 NOTREACHED() << "Unable to pickle hello message proc id";
791 }
792#if defined(IPC_USES_READWRITE)
793 scoped_ptr<Message> hello;
morritace44fef2014-09-29 22:25:54794 if (remote_fd_pipe_.is_valid()) {
795 if (!msg->WriteBorrowingFile(remote_fd_pipe_.get())) {
[email protected]22b42c52010-12-20 06:59:23796 NOTREACHED() << "Unable to pickle hello message file descriptors";
797 }
798 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
799 }
800#endif // IPC_USES_READWRITE
801 output_queue_.push(msg.release());
802}
803
[email protected]2f60c9b2014-06-06 20:13:51804ChannelPosix::ReadState ChannelPosix::ReadData(
[email protected]3d5a60b2012-03-01 21:41:47805 char* buffer,
806 int buffer_len,
807 int* bytes_read) {
morritace44fef2014-09-29 22:25:54808 if (!pipe_.is_valid())
[email protected]3d5a60b2012-03-01 21:41:47809 return READ_FAILED;
810
[email protected]334f3022012-02-29 22:48:14811 struct msghdr msg = {0};
812
[email protected]3fcbd4b2012-06-05 01:54:46813 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)};
[email protected]334f3022012-02-29 22:48:14814 msg.msg_iov = &iov;
815 msg.msg_iovlen = 1;
816
817 msg.msg_control = input_cmsg_buf_;
818
819 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data
820 // is waiting on the pipe.
[email protected]334f3022012-02-29 22:48:14821#if defined(IPC_USES_READWRITE)
morritace44fef2014-09-29 22:25:54822 if (fd_pipe_.is_valid()) {
823 *bytes_read = HANDLE_EINTR(read(pipe_.get(), buffer, buffer_len));
[email protected]334f3022012-02-29 22:48:14824 msg.msg_controllen = 0;
825 } else
826#endif // IPC_USES_READWRITE
827 {
828 msg.msg_controllen = sizeof(input_cmsg_buf_);
morritace44fef2014-09-29 22:25:54829 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT));
[email protected]334f3022012-02-29 22:48:14830 }
[email protected]3d5a60b2012-03-01 21:41:47831 if (*bytes_read < 0) {
[email protected]334f3022012-02-29 22:48:14832 if (errno == EAGAIN) {
[email protected]3d5a60b2012-03-01 21:41:47833 return READ_PENDING;
[email protected]334f3022012-02-29 22:48:14834#if defined(OS_MACOSX)
835 } else if (errno == EPERM) {
836 // On OSX, reading from a pipe with no listener returns EPERM
837 // treat this as a special case to prevent spurious error messages
838 // to the console.
[email protected]3d5a60b2012-03-01 21:41:47839 return READ_FAILED;
[email protected]334f3022012-02-29 22:48:14840#endif // OS_MACOSX
841 } else if (errno == ECONNRESET || errno == EPIPE) {
[email protected]3d5a60b2012-03-01 21:41:47842 return READ_FAILED;
[email protected]334f3022012-02-29 22:48:14843 } else {
morritace44fef2014-09-29 22:25:54844 PLOG(ERROR) << "pipe error (" << pipe_.get() << ")";
[email protected]3d5a60b2012-03-01 21:41:47845 return READ_FAILED;
[email protected]334f3022012-02-29 22:48:14846 }
[email protected]3d5a60b2012-03-01 21:41:47847 } else if (*bytes_read == 0) {
[email protected]334f3022012-02-29 22:48:14848 // The pipe has closed...
[email protected]3d5a60b2012-03-01 21:41:47849 return READ_FAILED;
[email protected]334f3022012-02-29 22:48:14850 }
[email protected]3d5a60b2012-03-01 21:41:47851 DCHECK(*bytes_read);
[email protected]334f3022012-02-29 22:48:14852
853 CloseClientFileDescriptor();
854
855 // Read any file descriptors from the message.
856 if (!ExtractFileDescriptorsFromMsghdr(&msg))
[email protected]3d5a60b2012-03-01 21:41:47857 return READ_FAILED;
858 return READ_SUCCEEDED;
[email protected]334f3022012-02-29 22:48:14859}
860
861#if defined(IPC_USES_READWRITE)
[email protected]2f60c9b2014-06-06 20:13:51862bool ChannelPosix::ReadFileDescriptorsFromFDPipe() {
[email protected]334f3022012-02-29 22:48:14863 char dummy;
864 struct iovec fd_pipe_iov = { &dummy, 1 };
865
866 struct msghdr msg = { 0 };
867 msg.msg_iov = &fd_pipe_iov;
868 msg.msg_iovlen = 1;
869 msg.msg_control = input_cmsg_buf_;
870 msg.msg_controllen = sizeof(input_cmsg_buf_);
morritace44fef2014-09-29 22:25:54871 ssize_t bytes_received =
872 HANDLE_EINTR(recvmsg(fd_pipe_.get(), &msg, MSG_DONTWAIT));
[email protected]334f3022012-02-29 22:48:14873
874 if (bytes_received != 1)
875 return true; // No message waiting.
876
877 if (!ExtractFileDescriptorsFromMsghdr(&msg))
878 return false;
879 return true;
880}
881#endif
882
[email protected]d805c6a2012-03-08 12:30:28883// On Posix, we need to fix up the file descriptors before the input message
884// is dispatched.
885//
886// This will read from the input_fds_ (READWRITE mode only) and read more
887// handles from the FD pipe if necessary.
[email protected]2f60c9b2014-06-06 20:13:51888bool ChannelPosix::WillDispatchInputMessage(Message* msg) {
[email protected]334f3022012-02-29 22:48:14889 uint16 header_fds = msg->header()->num_fds;
890 if (!header_fds)
891 return true; // Nothing to do.
892
893 // The message has file descriptors.
894 const char* error = NULL;
895 if (header_fds > input_fds_.size()) {
896 // The message has been completely received, but we didn't get
897 // enough file descriptors.
898#if defined(IPC_USES_READWRITE)
899 if (!ReadFileDescriptorsFromFDPipe())
900 return false;
901 if (header_fds > input_fds_.size())
902#endif // IPC_USES_READWRITE
903 error = "Message needs unreceived descriptors";
904 }
905
906 if (header_fds > FileDescriptorSet::kMaxDescriptorsPerMessage)
907 error = "Message requires an excessive number of descriptors";
908
909 if (error) {
910 LOG(WARNING) << error
911 << " channel:" << this
912 << " message-type:" << msg->type()
913 << " header()->num_fds:" << header_fds;
[email protected]334f3022012-02-29 22:48:14914 // Abort the connection.
915 ClearInputFDs();
916 return false;
917 }
918
[email protected]7e9eecb62012-04-09 21:40:44919 // The shenaniganery below with &foo.front() requires input_fds_ to have
920 // contiguous underlying storage (such as a simple array or a std::vector).
921 // This is why the header warns not to make input_fds_ a deque<>.
morrita96693852014-09-24 20:11:45922 msg->file_descriptor_set()->AddDescriptorsToOwn(&input_fds_.front(),
923 header_fds);
[email protected]334f3022012-02-29 22:48:14924 input_fds_.erase(input_fds_.begin(), input_fds_.begin() + header_fds);
925 return true;
926}
927
[email protected]2f60c9b2014-06-06 20:13:51928bool ChannelPosix::DidEmptyInputBuffers() {
[email protected]3d5a60b2012-03-01 21:41:47929 // When the input data buffer is empty, the fds should be too. If this is
930 // not the case, we probably have a rogue renderer which is trying to fill
931 // our descriptor table.
932 return input_fds_.empty();
933}
934
[email protected]2f60c9b2014-06-06 20:13:51935bool ChannelPosix::ExtractFileDescriptorsFromMsghdr(msghdr* msg) {
[email protected]334f3022012-02-29 22:48:14936 // Check that there are any control messages. On OSX, CMSG_FIRSTHDR will
937 // return an invalid non-NULL pointer in the case that controllen == 0.
938 if (msg->msg_controllen == 0)
939 return true;
940
941 for (cmsghdr* cmsg = CMSG_FIRSTHDR(msg);
942 cmsg;
943 cmsg = CMSG_NXTHDR(msg, cmsg)) {
944 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
945 unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
946 DCHECK_EQ(0U, payload_len % sizeof(int));
947 const int* file_descriptors = reinterpret_cast<int*>(CMSG_DATA(cmsg));
948 unsigned num_file_descriptors = payload_len / 4;
949 input_fds_.insert(input_fds_.end(),
950 file_descriptors,
951 file_descriptors + num_file_descriptors);
952
953 // Check this after adding the FDs so we don't leak them.
954 if (msg->msg_flags & MSG_CTRUNC) {
955 ClearInputFDs();
956 return false;
957 }
958
959 return true;
960 }
961 }
962
963 // No file descriptors found, but that's OK.
964 return true;
965}
966
[email protected]2f60c9b2014-06-06 20:13:51967void ChannelPosix::ClearInputFDs() {
[email protected]7e9eecb62012-04-09 21:40:44968 for (size_t i = 0; i < input_fds_.size(); ++i) {
[email protected]d89eec82013-12-03 14:10:59969 if (IGNORE_EINTR(close(input_fds_[i])) < 0)
[email protected]334f3022012-02-29 22:48:14970 PLOG(ERROR) << "close ";
[email protected]334f3022012-02-29 22:48:14971 }
[email protected]7e9eecb62012-04-09 21:40:44972 input_fds_.clear();
[email protected]334f3022012-02-29 22:48:14973}
974
[email protected]2f60c9b2014-06-06 20:13:51975void ChannelPosix::QueueCloseFDMessage(int fd, int hops) {
[email protected]dc875dc2013-10-15 00:07:00976 switch (hops) {
977 case 1:
978 case 2: {
979 // Create the message
980 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
[email protected]753bb252013-11-04 22:28:12981 CLOSE_FD_MESSAGE_TYPE,
982 IPC::Message::PRIORITY_NORMAL));
[email protected]dc875dc2013-10-15 00:07:00983 if (!msg->WriteInt(hops - 1) || !msg->WriteInt(fd)) {
984 NOTREACHED() << "Unable to pickle close fd.";
985 }
986 // Send(msg.release());
987 output_queue_.push(msg.release());
988 break;
989 }
990
991 default:
992 NOTREACHED();
993 break;
994 }
995}
996
[email protected]2f60c9b2014-06-06 20:13:51997void ChannelPosix::HandleInternalMessage(const Message& msg) {
[email protected]334f3022012-02-29 22:48:14998 // The Hello message contains only the process id.
[email protected]ce208f872012-03-07 20:42:56999 PickleIterator iter(msg);
[email protected]dc875dc2013-10-15 00:07:001000
1001 switch (msg.type()) {
1002 default:
1003 NOTREACHED();
1004 break;
1005
1006 case Channel::HELLO_MESSAGE_TYPE:
1007 int pid;
1008 if (!msg.ReadInt(&iter, &pid))
1009 NOTREACHED();
[email protected]334f3022012-02-29 22:48:141010
1011#if defined(IPC_USES_READWRITE)
[email protected]dc875dc2013-10-15 00:07:001012 if (mode_ & MODE_SERVER_FLAG) {
1013 // With IPC_USES_READWRITE, the Hello message from the client to the
1014 // server also contains the fd_pipe_, which will be used for all
1015 // subsequent file descriptor passing.
1016 DCHECK_EQ(msg.file_descriptor_set()->size(), 1U);
morrita96693852014-09-24 20:11:451017 base::ScopedFD descriptor;
1018 if (!msg.ReadFile(&iter, &descriptor)) {
[email protected]dc875dc2013-10-15 00:07:001019 NOTREACHED();
1020 }
morritace44fef2014-09-29 22:25:541021 fd_pipe_.reset(descriptor.release());
[email protected]dc875dc2013-10-15 00:07:001022 }
[email protected]787f5e462013-10-11 04:22:341023#endif // IPC_USES_READWRITE
[email protected]dc875dc2013-10-15 00:07:001024 peer_pid_ = pid;
1025 listener()->OnChannelConnected(pid);
1026 break;
1027
1028#if defined(OS_MACOSX)
1029 case Channel::CLOSE_FD_MESSAGE_TYPE:
1030 int fd, hops;
1031 if (!msg.ReadInt(&iter, &hops))
1032 NOTREACHED();
1033 if (!msg.ReadInt(&iter, &fd))
1034 NOTREACHED();
1035 if (hops == 0) {
1036 if (fds_to_close_.erase(fd) > 0) {
[email protected]d89eec82013-12-03 14:10:591037 if (IGNORE_EINTR(close(fd)) < 0)
[email protected]dc875dc2013-10-15 00:07:001038 PLOG(ERROR) << "close";
1039 } else {
1040 NOTREACHED();
1041 }
1042 } else {
1043 QueueCloseFDMessage(fd, hops);
1044 }
1045 break;
1046#endif
1047 }
[email protected]334f3022012-02-29 22:48:141048}
1049
[email protected]2f60c9b2014-06-06 20:13:511050void ChannelPosix::Close() {
[email protected]fa95fc92008-12-08 18:10:141051 // Close can be called multiple time, so we need to make sure we're
1052 // idempotent.
1053
[email protected]22b42c52010-12-20 06:59:231054 ResetToAcceptingConnectionState();
[email protected]fa95fc92008-12-08 18:10:141055
[email protected]22b42c52010-12-20 06:59:231056 if (must_unlink_) {
1057 unlink(pipe_name_.c_str());
1058 must_unlink_ = false;
1059 }
morritace44fef2014-09-29 22:25:541060
1061 if (server_listen_pipe_.is_valid()) {
hidehiko853d6082014-11-05 23:51:521062#if defined(OS_NACL_NONSFI)
hidehikoc2eec0d2014-10-24 03:49:271063 LOG(FATAL)
1064 << "IPC channels in nacl_helper_nonsfi should not be SERVER mode.";
1065#else
morritace44fef2014-09-29 22:25:541066 server_listen_pipe_.reset();
[email protected]22b42c52010-12-20 06:59:231067 // Unregister libevent for the listening socket and close it.
1068 server_listen_connection_watcher_.StopWatchingFileDescriptor();
hidehikoc2eec0d2014-10-24 03:49:271069#endif
[email protected]fa95fc92008-12-08 18:10:141070 }
1071
[email protected]2ce26c432011-09-19 17:08:121072 CloseClientFileDescriptor();
[email protected]fa95fc92008-12-08 18:10:141073}
1074
[email protected]2f60c9b2014-06-06 20:13:511075base::ProcessId ChannelPosix::GetPeerPID() const {
1076 return peer_pid_;
1077}
1078
[email protected]64860882014-08-04 23:44:171079base::ProcessId ChannelPosix::GetSelfPID() const {
1080 return GetHelloMessageProcId();
1081}
1082
[email protected]514411fc2008-12-10 22:28:111083//------------------------------------------------------------------------------
[email protected]2f60c9b2014-06-06 20:13:511084// Channel's methods
[email protected]22b42c52010-12-20 06:59:231085
[email protected]313c00e52011-08-09 06:46:061086// static
[email protected]2f60c9b2014-06-06 20:13:511087scoped_ptr<Channel> Channel::Create(
1088 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) {
dchengecc340f2014-10-17 00:43:541089 return make_scoped_ptr(new ChannelPosix(channel_handle, mode, listener));
[email protected]313c00e52011-08-09 06:46:061090}
1091
[email protected]5c41e6e12012-03-17 02:20:461092// static
1093std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) {
1094 // A random name is sufficient validation on posix systems, so we don't need
1095 // an additional shared secret.
1096
1097 std::string id = prefix;
1098 if (!id.empty())
1099 id.append(".");
1100
1101 return id.append(GenerateUniqueRandomChannelID());
1102}
1103
1104
[email protected]2f60c9b2014-06-06 20:13:511105bool Channel::IsNamedServerInitialized(
1106 const std::string& channel_id) {
1107 return ChannelPosix::IsNamedServerInitialized(channel_id);
1108}
1109
perkjdbcac352014-12-11 17:27:581110#if defined(OS_LINUX)
1111// static
1112void Channel::SetGlobalPid(int pid) {
1113 ChannelPosix::SetGlobalPid(pid);
1114}
1115#endif // OS_LINUX
1116
[email protected]d4651ff2008-12-02 16:51:581117} // namespace IPC