1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 // Copyright (c) 2008 The Chromium Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6
7 #include "chrome/common/ipc_channel_posix.h"
8
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <limits.h>
12 #if defined(OS_MACOSX) || defined(OS_NETBSD)
13 # include <sched.h>
14 #endif
15 #include <stddef.h>
16 #include <unistd.h>
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/stat.h>
20 #include <sys/un.h>
21 #include <sys/uio.h>
22
23 #include <string>
24 #include <map>
25
26 #include "base/command_line.h"
27 #include "base/eintr_wrapper.h"
28 #include "base/logging.h"
29 #include "base/process_util.h"
30 #include "base/string_util.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/file_descriptor_set_posix.h"
33 #include "chrome/common/ipc_channel_utils.h"
34 #include "chrome/common/ipc_message_utils.h"
35 #include "mozilla/ipc/Endpoint.h"
36 #include "mozilla/ipc/ProtocolUtils.h"
37 #include "mozilla/Atomics.h"
38 #include "mozilla/StaticMutex.h"
39 #include "mozilla/UniquePtr.h"
40 #include "mozilla/Unused.h"
41
42 #ifdef FUZZING
43 # include "mozilla/ipc/Faulty.h"
44 #endif
45
46 // Use OS specific iovec array limit where it's possible.
47 #if defined(IOV_MAX)
48 static const size_t kMaxIOVecSize = IOV_MAX;
49 #elif defined(ANDROID)
50 static const size_t kMaxIOVecSize = 256;
51 #else
52 static const size_t kMaxIOVecSize = 16;
53 #endif
54
55 using namespace mozilla::ipc;
56
57 namespace IPC {
58
59 // IPC channels on Windows use named pipes (CreateNamedPipe()) with
60 // channel ids as the pipe names. Channels on POSIX use anonymous
61 // Unix domain sockets created via socketpair() as pipes. These don't
62 // quite line up.
63 //
64 // When creating a child subprocess, the parent side of the fork
65 // arranges it such that the initial control channel ends up on the
66 // magic file descriptor gClientChannelFd in the child. Future
67 // connections (file descriptors) can then be passed via that
68 // connection via sendmsg().
69 //
70 // On Android, child processes are created as a service instead of
71 // forking the parent process. The Android Binder service is used to
72 // transport the IPC channel file descriptor to the child process.
73 // So rather than re-mapping the file descriptor to a known value,
74 // the received channel file descriptor is set by calling
75 // SetClientChannelFd before gecko has been initialized and started
76 // in the child process.
77
78 //------------------------------------------------------------------------------
79 namespace {
80
81 // This is the file descriptor number that a client process expects to find its
82 // IPC socket.
83 static int gClientChannelFd =
84 #if defined(MOZ_WIDGET_ANDROID)
85 // On android the fd is set at the time of child creation.
86 -1
87 #else
88 3
89 #endif // defined(MOZ_WIDGET_ANDROID)
90 ;
91
92 //------------------------------------------------------------------------------
93 const size_t kMaxPipeNameLength = sizeof(((sockaddr_un*)0)->sun_path);
94
SetCloseOnExec(int fd)95 bool SetCloseOnExec(int fd) {
96 int flags = fcntl(fd, F_GETFD);
97 if (flags == -1) return false;
98
99 flags |= FD_CLOEXEC;
100 if (fcntl(fd, F_SETFD, flags) == -1) return false;
101
102 return true;
103 }
104
ErrorIsBrokenPipe(int err)105 bool ErrorIsBrokenPipe(int err) { return err == EPIPE || err == ECONNRESET; }
106
107 // Some Android ARM64 devices appear to have a bug where sendmsg
108 // sometimes returns 0xFFFFFFFF, which we're assuming is a -1 that was
109 // incorrectly truncated to 32-bit and then zero-extended.
110 // See bug 1660826 for details.
111 //
112 // This is a workaround to detect that value and replace it with -1
113 // (and check that there really was an error), because the largest
114 // amount we'll ever write is Channel::kMaximumMessageSize (256MiB).
115 //
116 // The workaround is also enabled on x86_64 Android on debug builds,
117 // although the bug isn't known to manifest there, so that there will
118 // be some CI coverage of this code.
119
corrected_sendmsg(int socket,const struct msghdr * message,int flags)120 static inline ssize_t corrected_sendmsg(int socket,
121 const struct msghdr* message,
122 int flags) {
123 #if defined(ANDROID) && \
124 (defined(__aarch64__) || (defined(DEBUG) && defined(__x86_64__)))
125 static constexpr auto kBadValue = static_cast<ssize_t>(0xFFFFFFFF);
126 static_assert(kBadValue > 0);
127
128 # ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
129 errno = 0;
130 # endif
131 ssize_t bytes_written = sendmsg(socket, message, flags);
132 if (bytes_written == kBadValue) {
133 MOZ_DIAGNOSTIC_ASSERT(errno != 0);
134 bytes_written = -1;
135 }
136 MOZ_DIAGNOSTIC_ASSERT(bytes_written < kBadValue);
137 return bytes_written;
138 #else
139 return sendmsg(socket, message, flags);
140 #endif
141 }
142
143 } // namespace
144 //------------------------------------------------------------------------------
145
146 #if defined(MOZ_WIDGET_ANDROID)
SetClientChannelFd(int fd)147 void Channel::SetClientChannelFd(int fd) { gClientChannelFd = fd; }
148 #endif // defined(MOZ_WIDGET_ANDROID)
149
ChannelImpl(const ChannelId & channel_id,Mode mode,Listener * listener)150 Channel::ChannelImpl::ChannelImpl(const ChannelId& channel_id, Mode mode,
151 Listener* listener)
152 : factory_(this) {
153 Init(mode, listener);
154
155 if (!CreatePipe(mode)) {
156 CHROMIUM_LOG(WARNING) << "Unable to create pipe in "
157 << (mode == MODE_SERVER ? "server" : "client")
158 << " mode error(" << strerror(errno) << ").";
159 closed_ = true;
160 return;
161 }
162
163 EnqueueHelloMessage();
164 }
165
ChannelImpl(int fd,Mode mode,Listener * listener)166 Channel::ChannelImpl::ChannelImpl(int fd, Mode mode, Listener* listener)
167 : factory_(this) {
168 Init(mode, listener);
169 SetPipe(fd);
170 waiting_connect_ = (MODE_SERVER == mode);
171
172 EnqueueHelloMessage();
173 }
174
SetPipe(int fd)175 void Channel::ChannelImpl::SetPipe(int fd) {
176 pipe_ = fd;
177 pipe_buf_len_ = 0;
178 if (fd >= 0) {
179 int buf_len;
180 socklen_t optlen = sizeof(buf_len);
181 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_len, &optlen) != 0) {
182 CHROMIUM_LOG(WARNING)
183 << "Unable to determine pipe buffer size: " << strerror(errno);
184 return;
185 }
186 CHECK(optlen == sizeof(buf_len));
187 CHECK(buf_len > 0);
188 pipe_buf_len_ = static_cast<unsigned>(buf_len);
189 }
190 }
191
PipeBufHasSpaceAfter(size_t already_written)192 bool Channel::ChannelImpl::PipeBufHasSpaceAfter(size_t already_written) {
193 // If the OS didn't tell us the buffer size for some reason, then
194 // don't apply this limitation on the amount we try to write.
195 return pipe_buf_len_ == 0 ||
196 static_cast<size_t>(pipe_buf_len_) > already_written;
197 }
198
Init(Mode mode,Listener * listener)199 void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
200 // Verify that we fit in a "quantum-spaced" jemalloc bucket.
201 static_assert(sizeof(*this) <= 512, "Exceeded expected size class");
202
203 DCHECK(kControlBufferHeaderSize >= CMSG_SPACE(0));
204
205 mode_ = mode;
206 is_blocked_on_write_ = false;
207 partial_write_iter_.reset();
208 input_buf_offset_ = 0;
209 input_buf_ = mozilla::MakeUnique<char[]>(Channel::kReadBufferSize);
210 input_cmsg_buf_ = mozilla::MakeUnique<char[]>(kControlBufferSize);
211 server_listen_pipe_ = -1;
212 SetPipe(-1);
213 client_pipe_ = -1;
214 listener_ = listener;
215 waiting_connect_ = true;
216 processing_incoming_ = false;
217 closed_ = false;
218 #if defined(OS_MACOSX)
219 last_pending_fd_id_ = 0;
220 #endif
221 output_queue_length_ = 0;
222 }
223
CreatePipe(Mode mode)224 bool Channel::ChannelImpl::CreatePipe(Mode mode) {
225 DCHECK(server_listen_pipe_ == -1 && pipe_ == -1);
226
227 if (mode == MODE_SERVER) {
228 // socketpair()
229 int pipe_fds[2];
230 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) {
231 mozilla::ipc::AnnotateCrashReportWithErrno(
232 CrashReporter::Annotation::IpcCreatePipeSocketPairErrno, errno);
233 return false;
234 }
235 // Set both ends to be non-blocking.
236 if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 ||
237 fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) {
238 mozilla::ipc::AnnotateCrashReportWithErrno(
239 CrashReporter::Annotation::IpcCreatePipeFcntlErrno, errno);
240 IGNORE_EINTR(close(pipe_fds[0]));
241 IGNORE_EINTR(close(pipe_fds[1]));
242 return false;
243 }
244
245 if (!SetCloseOnExec(pipe_fds[0]) || !SetCloseOnExec(pipe_fds[1])) {
246 mozilla::ipc::AnnotateCrashReportWithErrno(
247 CrashReporter::Annotation::IpcCreatePipeCloExecErrno, errno);
248 IGNORE_EINTR(close(pipe_fds[0]));
249 IGNORE_EINTR(close(pipe_fds[1]));
250 return false;
251 }
252
253 SetPipe(pipe_fds[0]);
254 client_pipe_ = pipe_fds[1];
255 } else {
256 static mozilla::Atomic<bool> consumed(false);
257 CHECK(!consumed.exchange(true))
258 << "child process main channel can be created only once";
259 SetPipe(gClientChannelFd);
260 waiting_connect_ = false;
261 }
262
263 return true;
264 }
265
266 /**
267 * Reset the file descriptor for communication with the peer.
268 */
ResetFileDescriptor(int fd)269 void Channel::ChannelImpl::ResetFileDescriptor(int fd) {
270 NS_ASSERTION(fd > 0 && fd == pipe_, "Invalid file descriptor");
271
272 EnqueueHelloMessage();
273 }
274
EnqueueHelloMessage()275 bool Channel::ChannelImpl::EnqueueHelloMessage() {
276 mozilla::UniquePtr<Message> msg(
277 new Message(MSG_ROUTING_NONE, HELLO_MESSAGE_TYPE));
278 if (!msg->WriteInt(base::GetCurrentProcId())) {
279 Close();
280 return false;
281 }
282
283 OutputQueuePush(std::move(msg));
284 return true;
285 }
286
Connect()287 bool Channel::ChannelImpl::Connect() {
288 if (pipe_ == -1) {
289 return false;
290 }
291
292 MessageLoopForIO::current()->WatchFileDescriptor(
293 pipe_, true, MessageLoopForIO::WATCH_READ, &read_watcher_, this);
294 waiting_connect_ = false;
295
296 if (!waiting_connect_) return ProcessOutgoingMessages();
297 return true;
298 }
299
ProcessIncomingMessages()300 bool Channel::ChannelImpl::ProcessIncomingMessages() {
301 struct msghdr msg = {0};
302 struct iovec iov;
303
304 msg.msg_iov = &iov;
305 msg.msg_iovlen = 1;
306 msg.msg_control = input_cmsg_buf_.get();
307
308 for (;;) {
309 msg.msg_controllen = kControlBufferSize;
310
311 if (pipe_ == -1) return false;
312
313 // In some cases the beginning of a message will be stored in input_buf_. We
314 // don't want to overwrite that, so we store the new data after it.
315 iov.iov_base = input_buf_.get() + input_buf_offset_;
316 iov.iov_len = Channel::kReadBufferSize - input_buf_offset_;
317
318 // Read from pipe.
319 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data
320 // is waiting on the pipe.
321 ssize_t bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
322
323 if (bytes_read < 0) {
324 if (errno == EAGAIN) {
325 return true;
326 } else {
327 if (!ErrorIsBrokenPipe(errno)) {
328 CHROMIUM_LOG(ERROR)
329 << "pipe error (fd " << pipe_ << "): " << strerror(errno);
330 }
331 return false;
332 }
333 } else if (bytes_read == 0) {
334 // The pipe has closed...
335 Close();
336 return false;
337 }
338 DCHECK(bytes_read);
339
340 // a pointer to an array of |num_wire_fds| file descriptors from the read
341 const int* wire_fds = NULL;
342 unsigned num_wire_fds = 0;
343
344 // walk the list of control messages and, if we find an array of file
345 // descriptors, save a pointer to the array
346
347 // This next if statement is to work around an OSX issue where
348 // CMSG_FIRSTHDR will return non-NULL in the case that controllen == 0.
349 // Here's a test case:
350 //
351 // int main() {
352 // struct msghdr msg;
353 // msg.msg_control = &msg;
354 // msg.msg_controllen = 0;
355 // if (CMSG_FIRSTHDR(&msg))
356 // printf("Bug found!\n");
357 // }
358 if (msg.msg_controllen > 0) {
359 // On OSX, CMSG_FIRSTHDR doesn't handle the case where controllen is 0
360 // and will return a pointer into nowhere.
361 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg;
362 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
363 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
364 const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0);
365 DCHECK(payload_len % sizeof(int) == 0);
366 wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
367 num_wire_fds = payload_len / 4;
368
369 if (msg.msg_flags & MSG_CTRUNC) {
370 CHROMIUM_LOG(ERROR)
371 << "SCM_RIGHTS message was truncated"
372 << " cmsg_len:" << cmsg->cmsg_len << " fd:" << pipe_;
373 for (unsigned i = 0; i < num_wire_fds; ++i)
374 IGNORE_EINTR(close(wire_fds[i]));
375 return false;
376 }
377 break;
378 }
379 }
380 }
381
382 // Process messages from input buffer.
383 const char* p = input_buf_.get();
384 const char* end = input_buf_.get() + input_buf_offset_ + bytes_read;
385
386 // A pointer to an array of |num_fds| file descriptors which includes any
387 // fds that have spilled over from a previous read.
388 const int* fds;
389 unsigned num_fds;
390 unsigned fds_i = 0; // the index of the first unused descriptor
391
392 if (input_overflow_fds_.empty()) {
393 fds = wire_fds;
394 num_fds = num_wire_fds;
395 } else {
396 // This code may look like a no-op in the case where
397 // num_wire_fds == 0, but in fact:
398 //
399 // 1. wire_fds will be nullptr, so passing it to memcpy is
400 // undefined behavior according to the C standard, even though
401 // the memcpy length is 0.
402 //
403 // 2. prev_size will be an out-of-bounds index for
404 // input_overflow_fds_; this is undefined behavior according to
405 // the C++ standard, even though the element only has its
406 // pointer taken and isn't accessed (and the corresponding
407 // operation on a C array would be defined).
408 //
409 // UBSan makes #1 a fatal error, and assertions in libstdc++ do
410 // the same for #2 if enabled.
411 if (num_wire_fds > 0) {
412 const size_t prev_size = input_overflow_fds_.size();
413 input_overflow_fds_.resize(prev_size + num_wire_fds);
414 memcpy(&input_overflow_fds_[prev_size], wire_fds,
415 num_wire_fds * sizeof(int));
416 }
417 fds = &input_overflow_fds_[0];
418 num_fds = input_overflow_fds_.size();
419 }
420
421 // The data for the message we're currently reading consists of any data
422 // stored in incoming_message_ followed by data in input_buf_ (followed by
423 // other messages).
424
425 while (p < end) {
426 // Try to figure out how big the message is. Size is 0 if we haven't read
427 // enough of the header to know the size.
428 uint32_t message_length = 0;
429 if (incoming_message_.isSome()) {
430 message_length = incoming_message_.ref().size();
431 } else {
432 message_length = Message::MessageSize(p, end);
433 }
434
435 if (!message_length) {
436 // We haven't seen the full message header.
437 MOZ_ASSERT(incoming_message_.isNothing());
438
439 // Move everything we have to the start of the buffer. We'll finish
440 // reading this message when we get more data. For now we leave it in
441 // input_buf_.
442 memmove(input_buf_.get(), p, end - p);
443 input_buf_offset_ = end - p;
444
445 break;
446 }
447
448 input_buf_offset_ = 0;
449
450 bool partial;
451 if (incoming_message_.isSome()) {
452 // We already have some data for this message stored in
453 // incoming_message_. We want to append the new data there.
454 Message& m = incoming_message_.ref();
455
456 // How much data from this message remains to be added to
457 // incoming_message_?
458 MOZ_DIAGNOSTIC_ASSERT(message_length > m.CurrentSize());
459 uint32_t remaining = message_length - m.CurrentSize();
460
461 // How much data from this message is stored in input_buf_?
462 uint32_t in_buf = std::min(remaining, uint32_t(end - p));
463
464 m.InputBytes(p, in_buf);
465 p += in_buf;
466
467 // Are we done reading this message?
468 partial = in_buf != remaining;
469 } else {
470 // How much data from this message is stored in input_buf_?
471 uint32_t in_buf = std::min(message_length, uint32_t(end - p));
472
473 incoming_message_.emplace(p, in_buf);
474 p += in_buf;
475
476 // Are we done reading this message?
477 partial = in_buf != message_length;
478 }
479
480 if (partial) {
481 break;
482 }
483
484 Message& m = incoming_message_.ref();
485
486 if (m.header()->num_fds) {
487 // the message has file descriptors
488 const char* error = NULL;
489 if (m.header()->num_fds > num_fds - fds_i) {
490 // the message has been completely received, but we didn't get
491 // enough file descriptors.
492 error = "Message needs unreceived descriptors";
493 }
494
495 if (m.header()->num_fds >
496 FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE) {
497 // There are too many descriptors in this message
498 error = "Message requires an excessive number of descriptors";
499 }
500
501 if (error) {
502 CHROMIUM_LOG(WARNING)
503 << error << " channel:" << this << " message-type:" << m.type()
504 << " header()->num_fds:" << m.header()->num_fds
505 << " num_fds:" << num_fds << " fds_i:" << fds_i;
506 // close the existing file descriptors so that we don't leak them
507 for (unsigned i = fds_i; i < num_fds; ++i)
508 IGNORE_EINTR(close(fds[i]));
509 input_overflow_fds_.clear();
510 // abort the connection
511 return false;
512 }
513
514 #if defined(OS_MACOSX)
515 // Send a message to the other side, indicating that we are now
516 // responsible for closing the descriptor.
517 auto fdAck = mozilla::MakeUnique<Message>(MSG_ROUTING_NONE,
518 RECEIVED_FDS_MESSAGE_TYPE);
519 DCHECK(m.fd_cookie() != 0);
520 fdAck->set_fd_cookie(m.fd_cookie());
521 OutputQueuePush(std::move(fdAck));
522 #endif
523
524 m.file_descriptor_set()->SetDescriptors(&fds[fds_i],
525 m.header()->num_fds);
526 fds_i += m.header()->num_fds;
527 }
528
529 // Note: We set other_pid_ below when we receive a Hello message (which
530 // has no routing ID), but we only emit a profiler marker for messages
531 // with a routing ID, so there's no conflict here.
532 AddIPCProfilerMarker(m, other_pid_, MessageDirection::eReceiving,
533 MessagePhase::TransferEnd);
534
535 #ifdef IPC_MESSAGE_DEBUG_EXTRA
536 DLOG(INFO) << "received message on channel @" << this << " with type "
537 << m.type();
538 #endif
539
540 if (m.routing_id() == MSG_ROUTING_NONE &&
541 m.type() == HELLO_MESSAGE_TYPE) {
542 // The Hello message contains only the process id.
543 other_pid_ = MessageIterator(m).NextInt();
544 listener_->OnChannelConnected(other_pid_);
545 #if defined(OS_MACOSX)
546 } else if (m.routing_id() == MSG_ROUTING_NONE &&
547 m.type() == RECEIVED_FDS_MESSAGE_TYPE) {
548 DCHECK(m.fd_cookie() != 0);
549 CloseDescriptors(m.fd_cookie());
550 #endif
551 } else {
552 mozilla::LogIPCMessage::Run run(&m);
553 listener_->OnMessageReceived(std::move(m));
554 }
555
556 incoming_message_.reset();
557 }
558
559 input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]);
560
561 // When the input data buffer is empty, the overflow fds should be too. If
562 // this is not the case, we probably have a rogue renderer which is trying
563 // to fill our descriptor table.
564 if (incoming_message_.isNothing() && input_buf_offset_ == 0 &&
565 !input_overflow_fds_.empty()) {
566 // We close these descriptors in Close()
567 return false;
568 }
569 }
570
571 return true;
572 }
573
ProcessOutgoingMessages()574 bool Channel::ChannelImpl::ProcessOutgoingMessages() {
575 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
576 // no connection?
577 is_blocked_on_write_ = false;
578
579 if (output_queue_.IsEmpty()) return true;
580
581 if (pipe_ == -1) return false;
582
583 // Write out all the messages we can till the write blocks or there are no
584 // more outgoing messages.
585 while (!output_queue_.IsEmpty()) {
586 #ifdef FUZZING
587 mozilla::ipc::Faulty::instance().MaybeCollectAndClosePipe(pipe_);
588 #endif
589 Message* msg = output_queue_.FirstElement().get();
590
591 struct msghdr msgh = {0};
592
593 static const int tmp =
594 CMSG_SPACE(sizeof(int[FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE]));
595 char buf[tmp];
596
597 if (partial_write_iter_.isNothing()) {
598 Pickle::BufferList::IterImpl iter(msg->Buffers());
599 MOZ_DIAGNOSTIC_ASSERT(!iter.Done(), "empty message");
600 partial_write_iter_.emplace(iter);
601 }
602
603 if (partial_write_iter_.ref().Done()) {
604 MOZ_DIAGNOSTIC_ASSERT(false, "partial_write_iter_ should not be null");
605 // report a send error to our caller, which will close the channel.
606 return false;
607 }
608
609 if (partial_write_iter_.value().Data() == msg->Buffers().Start()) {
610 AddIPCProfilerMarker(*msg, other_pid_, MessageDirection::eSending,
611 MessagePhase::TransferStart);
612
613 if (!msg->file_descriptor_set()->empty()) {
614 // This is the first chunk of a message which has descriptors to send
615 struct cmsghdr* cmsg;
616 const unsigned num_fds = msg->file_descriptor_set()->size();
617
618 if (num_fds > FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE) {
619 MOZ_DIAGNOSTIC_ASSERT(false, "Too many file descriptors!");
620 CHROMIUM_LOG(FATAL) << "Too many file descriptors!";
621 // This should not be reached.
622 return false;
623 }
624
625 msgh.msg_control = buf;
626 msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
627 cmsg = CMSG_FIRSTHDR(&msgh);
628 cmsg->cmsg_level = SOL_SOCKET;
629 cmsg->cmsg_type = SCM_RIGHTS;
630 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
631 msg->file_descriptor_set()->GetDescriptors(
632 reinterpret_cast<int*>(CMSG_DATA(cmsg)));
633 msgh.msg_controllen = cmsg->cmsg_len;
634
635 msg->header()->num_fds = num_fds;
636 #if defined(OS_MACOSX)
637 msg->set_fd_cookie(++last_pending_fd_id_);
638 #endif
639 }
640 }
641
642 struct iovec iov[kMaxIOVecSize];
643 size_t iov_count = 0;
644 size_t amt_to_write = 0;
645
646 // How much of this message have we written so far?
647 Pickle::BufferList::IterImpl iter = partial_write_iter_.value();
648
649 // Store the unwritten part of the first segment to write into the iovec.
650 iov[0].iov_base = const_cast<char*>(iter.Data());
651 iov[0].iov_len = iter.RemainingInSegment();
652 amt_to_write += iov[0].iov_len;
653 iter.Advance(msg->Buffers(), iov[0].iov_len);
654 iov_count++;
655
656 // Store remaining segments to write into iovec.
657 //
658 // Don't add more than kMaxIOVecSize iovecs so that we avoid
659 // OS-dependent limits. Also, stop adding iovecs if we've already
660 // prepared to write at least the full buffer size.
661 while (!iter.Done() && iov_count < kMaxIOVecSize &&
662 PipeBufHasSpaceAfter(amt_to_write)) {
663 char* data = iter.Data();
664 size_t size = iter.RemainingInSegment();
665
666 iov[iov_count].iov_base = data;
667 iov[iov_count].iov_len = size;
668 iov_count++;
669 amt_to_write += size;
670 iter.Advance(msg->Buffers(), size);
671 }
672
673 const bool intentional_short_write = !iter.Done();
674 msgh.msg_iov = iov;
675 msgh.msg_iovlen = iov_count;
676
677 ssize_t bytes_written =
678 HANDLE_EINTR(corrected_sendmsg(pipe_, &msgh, MSG_DONTWAIT));
679
680 #if !defined(OS_MACOSX)
681 // On OSX CommitAll gets called later, once we get the
682 // RECEIVED_FDS_MESSAGE_TYPE message.
683 if (bytes_written > 0) msg->file_descriptor_set()->CommitAll();
684 #endif
685
686 if (bytes_written < 0) {
687 switch (errno) {
688 case EAGAIN:
689 // Not an error; the sendmsg would have blocked, so return to the
690 // event loop and try again later.
691 break;
692 #if defined(OS_MACOSX) || defined(OS_NETBSD)
693 // (Note: this comment is copied from https://crrev.com/86c3d9ef4fdf6;
694 // see also bug 1142693 comment #73.)
695 //
696 // On OS X if sendmsg() is trying to send fds between processes and
697 // there isn't enough room in the output buffer to send the fd
698 // structure over atomically then EMSGSIZE is returned. The same
699 // applies to NetBSD as well.
700 //
701 // EMSGSIZE presents a problem since the system APIs can only call us
702 // when there's room in the socket buffer and not when there is
703 // "enough" room.
704 //
705 // The current behavior is to return to the event loop when EMSGSIZE
706 // is received and hopefull service another FD. This is however still
707 // technically a busy wait since the event loop will call us right
708 // back until the receiver has read enough data to allow passing the
709 // FD over atomically.
710 case EMSGSIZE:
711 // Because this is likely to result in a busy-wait, we'll try to make
712 // it easier for the receiver to make progress.
713 sched_yield();
714 break;
715 #endif
716 default:
717 if (!ErrorIsBrokenPipe(errno)) {
718 CHROMIUM_LOG(ERROR) << "pipe error: " << strerror(errno);
719 }
720 return false;
721 }
722 }
723
724 if (intentional_short_write ||
725 static_cast<size_t>(bytes_written) != amt_to_write) {
726 // If write() fails with EAGAIN then bytes_written will be -1.
727 if (bytes_written > 0) {
728 MOZ_DIAGNOSTIC_ASSERT(intentional_short_write ||
729 static_cast<size_t>(bytes_written) <
730 amt_to_write);
731 partial_write_iter_.ref().AdvanceAcrossSegments(msg->Buffers(),
732 bytes_written);
733 // We should not hit the end of the buffer.
734 MOZ_DIAGNOSTIC_ASSERT(!partial_write_iter_.ref().Done());
735 }
736
737 // Tell libevent to call us back once things are unblocked.
738 is_blocked_on_write_ = true;
739 MessageLoopForIO::current()->WatchFileDescriptor(
740 pipe_,
741 false, // One shot
742 MessageLoopForIO::WATCH_WRITE, &write_watcher_, this);
743 return true;
744 } else {
745 partial_write_iter_.reset();
746
747 #if defined(OS_MACOSX)
748 if (!msg->file_descriptor_set()->empty())
749 pending_fds_.push_back(
750 PendingDescriptors(msg->fd_cookie(), msg->file_descriptor_set()));
751 #endif
752
753 // Message sent OK!
754
755 AddIPCProfilerMarker(*msg, other_pid_, MessageDirection::eSending,
756 MessagePhase::TransferEnd);
757
758 #ifdef IPC_MESSAGE_DEBUG_EXTRA
759 DLOG(INFO) << "sent message @" << msg << " on channel @" << this
760 << " with type " << msg->type();
761 #endif
762 OutputQueuePop();
763 // msg has been destroyed, so clear the dangling reference.
764 msg = nullptr;
765 }
766 }
767 return true;
768 }
769
Send(mozilla::UniquePtr<Message> message)770 bool Channel::ChannelImpl::Send(mozilla::UniquePtr<Message> message) {
771 #ifdef IPC_MESSAGE_DEBUG_EXTRA
772 DLOG(INFO) << "sending message @" << message.get() << " on channel @" << this
773 << " with type " << message->type() << " ("
774 << output_queue_.Count() << " in queue)";
775 #endif
776
777 #ifdef FUZZING
778 message = mozilla::ipc::Faulty::instance().MutateIPCMessage(
779 "Channel::ChannelImpl::Send", std::move(message));
780 #endif
781
782 // If the channel has been closed, ProcessOutgoingMessages() is never going
783 // to pop anything off output_queue; output_queue will only get emptied when
784 // the channel is destructed. We might as well delete message now, instead
785 // of waiting for the channel to be destructed.
786 if (closed_) {
787 if (mozilla::ipc::LoggingEnabled()) {
788 fprintf(stderr,
789 "Can't send message %s, because this channel is closed.\n",
790 message->name());
791 }
792 return false;
793 }
794
795 OutputQueuePush(std::move(message));
796 if (!waiting_connect_) {
797 if (!is_blocked_on_write_) {
798 if (!ProcessOutgoingMessages()) return false;
799 }
800 }
801
802 return true;
803 }
804
GetClientFileDescriptorMapping(int * src_fd,int * dest_fd) const805 void Channel::ChannelImpl::GetClientFileDescriptorMapping(int* src_fd,
806 int* dest_fd) const {
807 DCHECK(mode_ == MODE_SERVER);
808 *src_fd = client_pipe_;
809 *dest_fd = gClientChannelFd;
810 }
811
CloseClientFileDescriptor()812 void Channel::ChannelImpl::CloseClientFileDescriptor() {
813 if (client_pipe_ != -1) {
814 IGNORE_EINTR(close(client_pipe_));
815 client_pipe_ = -1;
816 }
817 }
818
819 // Called by libevent when we can read from th pipe without blocking.
OnFileCanReadWithoutBlocking(int fd)820 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) {
821 if (!waiting_connect_ && fd == pipe_) {
822 if (!ProcessIncomingMessages()) {
823 Close();
824 listener_->OnChannelError();
825 // The OnChannelError() call may delete this, so we need to exit now.
826 return;
827 }
828 }
829 }
830
831 #if defined(OS_MACOSX)
CloseDescriptors(uint32_t pending_fd_id)832 void Channel::ChannelImpl::CloseDescriptors(uint32_t pending_fd_id) {
833 DCHECK(pending_fd_id != 0);
834 for (std::list<PendingDescriptors>::iterator i = pending_fds_.begin();
835 i != pending_fds_.end(); i++) {
836 if ((*i).id == pending_fd_id) {
837 (*i).fds->CommitAll();
838 pending_fds_.erase(i);
839 return;
840 }
841 }
842 DCHECK(false) << "pending_fd_id not in our list!";
843 }
844 #endif
845
OutputQueuePush(mozilla::UniquePtr<Message> msg)846 void Channel::ChannelImpl::OutputQueuePush(mozilla::UniquePtr<Message> msg) {
847 mozilla::LogIPCMessage::LogDispatchWithPid(msg.get(), other_pid_);
848
849 MOZ_DIAGNOSTIC_ASSERT(!closed_);
850 msg->AssertAsLargeAsHeader();
851 output_queue_.Push(std::move(msg));
852 output_queue_length_++;
853 }
854
OutputQueuePop()855 void Channel::ChannelImpl::OutputQueuePop() {
856 // Clear any reference to the front of output_queue_ before we destroy it.
857 partial_write_iter_.reset();
858
859 mozilla::UniquePtr<Message> message = output_queue_.Pop();
860 output_queue_length_--;
861 }
862
863 // Called by libevent when we can write to the pipe without blocking.
OnFileCanWriteWithoutBlocking(int fd)864 void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) {
865 if (!ProcessOutgoingMessages()) {
866 Close();
867 listener_->OnChannelError();
868 }
869 }
870
Close()871 void Channel::ChannelImpl::Close() {
872 // Close can be called multiple times, so we need to make sure we're
873 // idempotent.
874
875 // Unregister libevent for the listening socket and close it.
876 server_listen_connection_watcher_.StopWatchingFileDescriptor();
877
878 if (server_listen_pipe_ != -1) {
879 IGNORE_EINTR(close(server_listen_pipe_));
880 server_listen_pipe_ = -1;
881 }
882
883 // Unregister libevent for the FIFO and close it.
884 read_watcher_.StopWatchingFileDescriptor();
885 write_watcher_.StopWatchingFileDescriptor();
886 if (pipe_ != -1) {
887 IGNORE_EINTR(close(pipe_));
888 SetPipe(-1);
889 }
890 if (client_pipe_ != -1) {
891 IGNORE_EINTR(close(client_pipe_));
892 client_pipe_ = -1;
893 }
894
895 while (!output_queue_.IsEmpty()) {
896 OutputQueuePop();
897 }
898
899 // Close any outstanding, received file descriptors
900 for (std::vector<int>::iterator i = input_overflow_fds_.begin();
901 i != input_overflow_fds_.end(); ++i) {
902 IGNORE_EINTR(close(*i));
903 }
904 input_overflow_fds_.clear();
905
906 #if defined(OS_MACOSX)
907 for (std::list<PendingDescriptors>::iterator i = pending_fds_.begin();
908 i != pending_fds_.end(); i++) {
909 (*i).fds->CommitAll();
910 }
911 pending_fds_.clear();
912 #endif
913
914 closed_ = true;
915 }
916
Unsound_IsClosed() const917 bool Channel::ChannelImpl::Unsound_IsClosed() const { return closed_; }
918
Unsound_NumQueuedMessages() const919 uint32_t Channel::ChannelImpl::Unsound_NumQueuedMessages() const {
920 return output_queue_length_;
921 }
922
923 //------------------------------------------------------------------------------
924 // Channel's methods simply call through to ChannelImpl.
Channel(const ChannelId & channel_id,Mode mode,Listener * listener)925 Channel::Channel(const ChannelId& channel_id, Mode mode, Listener* listener)
926 : channel_impl_(new ChannelImpl(channel_id, mode, listener)) {
927 MOZ_COUNT_CTOR(IPC::Channel);
928 }
929
Channel(int fd,Mode mode,Listener * listener)930 Channel::Channel(int fd, Mode mode, Listener* listener)
931 : channel_impl_(new ChannelImpl(fd, mode, listener)) {
932 MOZ_COUNT_CTOR(IPC::Channel);
933 }
934
~Channel()935 Channel::~Channel() {
936 MOZ_COUNT_DTOR(IPC::Channel);
937 delete channel_impl_;
938 }
939
Connect()940 bool Channel::Connect() { return channel_impl_->Connect(); }
941
Close()942 void Channel::Close() { channel_impl_->Close(); }
943
set_listener(Listener * listener)944 Channel::Listener* Channel::set_listener(Listener* listener) {
945 return channel_impl_->set_listener(listener);
946 }
947
Send(mozilla::UniquePtr<Message> message)948 bool Channel::Send(mozilla::UniquePtr<Message> message) {
949 return channel_impl_->Send(std::move(message));
950 }
951
GetClientFileDescriptorMapping(int * src_fd,int * dest_fd) const952 void Channel::GetClientFileDescriptorMapping(int* src_fd, int* dest_fd) const {
953 return channel_impl_->GetClientFileDescriptorMapping(src_fd, dest_fd);
954 }
955
ResetFileDescriptor(int fd)956 void Channel::ResetFileDescriptor(int fd) {
957 channel_impl_->ResetFileDescriptor(fd);
958 }
959
GetFileDescriptor() const960 int Channel::GetFileDescriptor() const {
961 return channel_impl_->GetFileDescriptor();
962 }
963
CloseClientFileDescriptor()964 void Channel::CloseClientFileDescriptor() {
965 channel_impl_->CloseClientFileDescriptor();
966 }
967
OtherPid() const968 int32_t Channel::OtherPid() const { return channel_impl_->OtherPid(); }
969
Unsound_IsClosed() const970 bool Channel::Unsound_IsClosed() const {
971 return channel_impl_->Unsound_IsClosed();
972 }
973
Unsound_NumQueuedMessages() const974 uint32_t Channel::Unsound_NumQueuedMessages() const {
975 return channel_impl_->Unsound_NumQueuedMessages();
976 }
977
978 // static
GenerateVerifiedChannelID()979 Channel::ChannelId Channel::GenerateVerifiedChannelID() { return {}; }
980
981 // static
ChannelIDForCurrentProcess()982 Channel::ChannelId Channel::ChannelIDForCurrentProcess() { return {}; }
983
984 } // namespace IPC
985