ipc_channel_posix.h (7015B)
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 #ifndef CHROME_COMMON_IPC_CHANNEL_POSIX_H_ 8 #define CHROME_COMMON_IPC_CHANNEL_POSIX_H_ 9 10 #include "chrome/common/ipc_channel.h" 11 12 #include <sys/socket.h> // for CMSG macros 13 14 #include <atomic> 15 #include <vector> 16 #include <list> 17 18 #include "base/message_loop.h" 19 #include "base/process.h" 20 #include "base/task.h" 21 22 #include "mozilla/EventTargetAndLockCapability.h" 23 #include "mozilla/Maybe.h" 24 #include "mozilla/Mutex.h" 25 #include "mozilla/Queue.h" 26 #include "mozilla/UniquePtr.h" 27 #include "mozilla/UniquePtrExtensions.h" 28 #include "nsISupports.h" 29 30 namespace IPC { 31 32 // An implementation of ChannelImpl for POSIX systems that works via 33 // socketpairs. See the .cc file for an overview of the implementation. 34 class ChannelPosix final : public Channel, public MessageLoopForIO::Watcher { 35 public: 36 ChannelPosix(mozilla::UniqueFileHandle pipe, Mode mode, 37 base::ProcessId other_pid); 38 39 bool Connect(Listener* listener) MOZ_EXCLUDES(SendMutex()) override; 40 void Close() MOZ_EXCLUDES(SendMutex()) override; 41 42 // NOTE: `Send` may be called on threads other than the I/O thread. 43 bool Send(mozilla::UniquePtr<Message> message) 44 MOZ_EXCLUDES(SendMutex()) override; 45 46 void SetOtherPid(base::ProcessId other_pid) override; 47 48 #if defined(XP_DARWIN) 49 void SetOtherMachTask(task_t task) MOZ_EXCLUDES(SendMutex()) override; 50 #endif 51 52 const ChannelKind* GetKind() const override { return &sKind; } 53 54 static const ChannelKind sKind; 55 56 private: 57 ~ChannelPosix() { Close(); } 58 59 static bool CreateRawPipe(ChannelHandle* server, ChannelHandle* client); 60 static uint32_t NumRelayedAttachments(const IPC::Message& message); 61 static bool IsValidHandle(const ChannelHandle& handle); 62 63 void Init(Mode mode) MOZ_REQUIRES(SendMutex(), IOThread()); 64 void SetPipe(int fd) MOZ_REQUIRES(SendMutex(), IOThread()); 65 bool PipeBufHasSpaceAfter(size_t already_written) 66 MOZ_REQUIRES_SHARED(chan_cap_); 67 bool EnqueueHelloMessage() MOZ_REQUIRES(SendMutex(), IOThread()); 68 bool ContinueConnect() MOZ_REQUIRES(SendMutex(), IOThread()); 69 void CloseLocked() MOZ_REQUIRES(SendMutex(), IOThread()); 70 71 bool ProcessIncomingMessages() MOZ_REQUIRES(IOThread()); 72 bool ProcessOutgoingMessages() MOZ_REQUIRES(SendMutex()); 73 74 // MessageLoopForIO::Watcher implementation. 75 virtual void OnFileCanReadWithoutBlocking(int fd) override; 76 virtual void OnFileCanWriteWithoutBlocking(int fd) override; 77 78 #if defined(XP_DARWIN) 79 void CloseDescriptors(uint32_t pending_fd_id) MOZ_REQUIRES(IOThread()) 80 MOZ_EXCLUDES(SendMutex()); 81 82 // Called on a Message immediately before it is sent/recieved to transfer 83 // handles to the remote process, or accept handles from the remote process. 84 bool AcceptMachPorts(Message& msg) MOZ_REQUIRES(IOThread()); 85 bool TransferMachPorts(Message& msg) MOZ_REQUIRES_SHARED(chan_cap_); 86 #endif 87 88 void OutputQueuePush(mozilla::UniquePtr<Message> msg) 89 MOZ_REQUIRES(SendMutex()); 90 void OutputQueuePop() MOZ_REQUIRES(SendMutex()); 91 92 Mode mode_ MOZ_GUARDED_BY(chan_cap_); 93 94 // After accepting one client connection on our server socket we want to 95 // stop listening. 96 MessageLoopForIO::FileDescriptorWatcher read_watcher_ 97 MOZ_GUARDED_BY(IOThread()); 98 MessageLoopForIO::FileDescriptorWatcher write_watcher_ 99 MOZ_GUARDED_BY(IOThread()); 100 101 // Indicates whether we're currently blocked waiting for a write to complete. 102 bool is_blocked_on_write_ MOZ_GUARDED_BY(SendMutex()) = false; 103 104 // If sending a message blocks then we use this iterator to keep track of 105 // where in the message we are. It gets reset when the message is finished 106 // sending. 107 struct PartialWrite { 108 Pickle::BufferList::IterImpl iter_; 109 mozilla::Span<const mozilla::UniqueFileHandle> handles_; 110 }; 111 mozilla::Maybe<PartialWrite> partial_write_ MOZ_GUARDED_BY(SendMutex()); 112 113 int pipe_ MOZ_GUARDED_BY(chan_cap_); 114 // The SO_SNDBUF value of pipe_, or 0 if unknown. 115 unsigned pipe_buf_len_ MOZ_GUARDED_BY(chan_cap_); 116 117 Listener* listener_ MOZ_GUARDED_BY(IOThread()); 118 119 // Messages to be sent are queued here. 120 mozilla::Queue<mozilla::UniquePtr<Message>, 64> output_queue_ 121 MOZ_GUARDED_BY(SendMutex()); 122 123 // We read from the pipe into these buffers. 124 size_t input_buf_offset_ MOZ_GUARDED_BY(IOThread()); 125 mozilla::UniquePtr<char[]> input_buf_ MOZ_GUARDED_BY(IOThread()); 126 mozilla::UniquePtr<char[]> input_cmsg_buf_ MOZ_GUARDED_BY(IOThread()); 127 128 // The control message buffer will hold all of the file descriptors that will 129 // be read in during a single recvmsg call. Message::WriteFileDescriptor 130 // always writes one word of data for every file descriptor added to the 131 // message, and the number of file descriptors per recvmsg will not exceed 132 // kControlBufferMaxFds. This is based on the true maximum SCM_RIGHTS 133 // descriptor count, which is just over 250 on both Linux and macOS. 134 // 135 // This buffer also holds a control message header of size CMSG_SPACE(0) 136 // bytes. However, CMSG_SPACE is not a constant on Macs, so we can't use it 137 // here. Consequently, we pick a number here that is at least CMSG_SPACE(0) on 138 // all platforms. We assert at runtime, in Channel::ChannelImpl::Init, that 139 // it's big enough. 140 static constexpr size_t kControlBufferMaxFds = 200; 141 static constexpr size_t kControlBufferHeaderSize = 32; 142 static constexpr size_t kControlBufferSize = 143 kControlBufferMaxFds * sizeof(int) + kControlBufferHeaderSize; 144 145 // Large incoming messages that span multiple pipe buffers get built-up in the 146 // buffers of this message. 147 mozilla::UniquePtr<Message> incoming_message_ MOZ_GUARDED_BY(IOThread()); 148 std::vector<int> input_overflow_fds_ MOZ_GUARDED_BY(IOThread()); 149 150 // Will be set to `true` until `Connect()` has been called and communication 151 // is ready. For privileged connections on macOS, this will not be cleared 152 // until the peer mach port has been provided to allow transferring mach 153 // ports. 154 bool waiting_connect_ MOZ_GUARDED_BY(chan_cap_) = true; 155 156 // We keep track of the PID of the other side of this channel so that we can 157 // record this when generating logs of IPC messages. 158 base::ProcessId other_pid_ MOZ_GUARDED_BY(chan_cap_) = 159 base::kInvalidProcessId; 160 161 #if defined(XP_DARWIN) 162 struct PendingDescriptors { 163 uint32_t id; 164 nsTArray<mozilla::UniqueFileHandle> handles; 165 }; 166 167 std::list<PendingDescriptors> pending_fds_ MOZ_GUARDED_BY(SendMutex()); 168 169 // A generation ID for RECEIVED_FD messages. 170 uint32_t last_pending_fd_id_ MOZ_GUARDED_BY(SendMutex()) = 0; 171 172 // If available, the task port for the remote process. 173 // Only used if mode_ == MODE_BROKER_SERVER. 174 mozilla::UniqueMachSendRight other_task_ MOZ_GUARDED_BY(chan_cap_); 175 #endif 176 }; 177 178 } // namespace IPC 179 180 #endif // CHROME_COMMON_IPC_CHANNEL_POSIX_H_