tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_