tor-browser

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

SharedMemoryHandle.h (8500B)


      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 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_ipc_SharedMemoryHandle_h
      8 #define mozilla_ipc_SharedMemoryHandle_h
      9 
     10 #include <utility>
     11 
     12 #include "mozilla/UniquePtrExtensions.h"
     13 
     14 namespace IPC {
     15 template <class P>
     16 struct ParamTraits;
     17 class MessageWriter;
     18 class MessageReader;
     19 }  // namespace IPC
     20 
     21 namespace mozilla::geckoargs {
     22 template <typename T>
     23 struct CommandLineArg;
     24 }
     25 
     26 namespace mozilla::ipc {
     27 
     28 namespace shared_memory {
     29 
     30 enum class Type {
     31  Mutable,
     32  ReadOnly,
     33  MutableOrReadOnly,
     34  Freezable,
     35 };
     36 
     37 #if defined(XP_DARWIN)
     38 using PlatformHandle = mozilla::UniqueMachSendRight;
     39 #else
     40 using PlatformHandle = mozilla::UniqueFileHandle;
     41 #endif
     42 
     43 template <Type T>
     44 struct Handle;
     45 
     46 template <Type T, bool WithHandle = false>
     47 struct Mapping;
     48 
     49 using MutableHandle = Handle<Type::Mutable>;
     50 using ReadOnlyHandle = Handle<Type::ReadOnly>;
     51 using FreezableHandle = Handle<Type::Freezable>;
     52 
     53 using MutableMapping = Mapping<Type::Mutable>;
     54 using ReadOnlyMapping = Mapping<Type::ReadOnly>;
     55 using MutableOrReadOnlyMapping = Mapping<Type::MutableOrReadOnly>;
     56 using FreezableMapping = Mapping<Type::Freezable>;
     57 
     58 using MutableMappingWithHandle = Mapping<Type::Mutable, true>;
     59 using ReadOnlyMappingWithHandle = Mapping<Type::ReadOnly, true>;
     60 
     61 class HandleBase {
     62 public:
     63  /**
     64   * The size of the shared memory region to which this handle refers.
     65   */
     66  uint64_t Size() const { return mSize; }
     67 
     68  /**
     69   * Whether this shared memory handle is valid.
     70   */
     71  bool IsValid() const { return (bool)*this; }
     72 
     73  /**
     74   * Whether this shared memory handle is valid.
     75   */
     76  explicit operator bool() const { return (bool)mHandle; }
     77 
     78  /**
     79   * Take the platform handle.
     80   *
     81   * This should be used with caution, as it drops all of the guarantees of the
     82   * shared memory handle classes.
     83   */
     84  PlatformHandle TakePlatformHandle() && { return std::move(mHandle); }
     85 
     86  friend class Platform;
     87  friend struct IPC::ParamTraits<mozilla::ipc::shared_memory::MutableHandle>;
     88  friend struct IPC::ParamTraits<mozilla::ipc::shared_memory::ReadOnlyHandle>;
     89  friend struct mozilla::geckoargs::CommandLineArg<
     90      mozilla::ipc::shared_memory::ReadOnlyHandle>;
     91 
     92 protected:
     93  HandleBase();
     94  MOZ_IMPLICIT HandleBase(std::nullptr_t) {}
     95  ~HandleBase();
     96 
     97  HandleBase(HandleBase&& aOther)
     98      : mHandle(std::move(aOther.mHandle)),
     99        mSize(std::exchange(aOther.mSize, 0)) {}
    100 
    101  HandleBase& operator=(HandleBase&& aOther);
    102 
    103  HandleBase(const HandleBase&) = delete;
    104  HandleBase& operator=(const HandleBase&) = delete;
    105 
    106  HandleBase Clone() const;
    107 
    108  template <Type T>
    109  Handle<T> CloneAs() const {
    110    return Clone().ConvertTo<T>();
    111  }
    112 
    113  template <Type T>
    114  Handle<T> ConvertTo() && {
    115    Handle<T> d;
    116    static_cast<HandleBase&>(d) = std::move(*this);
    117    return d;
    118  }
    119 
    120  void ToMessageWriter(IPC::MessageWriter* aWriter) &&;
    121  bool FromMessageReader(IPC::MessageReader* aReader);
    122 
    123 private:
    124  /**
    125   * Set the size of the handle.
    126   *
    127   * This method must be used rather than setting `mSize` directly, as there is
    128   * additional bookkeeping that goes along with this value.
    129   */
    130  void SetSize(uint64_t aSize);
    131 
    132  PlatformHandle mHandle = nullptr;
    133  uint64_t mSize = 0;
    134 };
    135 
    136 /**
    137 * A handle to a shared memory region.
    138 */
    139 template <>
    140 struct Handle<Type::Mutable> : HandleBase {
    141  /**
    142   * Create an empty Handle.
    143   */
    144  Handle() = default;
    145  MOZ_IMPLICIT Handle(std::nullptr_t) {}
    146 
    147  /**
    148   * Clone the handle.
    149   */
    150  Handle Clone() const { return CloneAs<Type::Mutable>(); }
    151 
    152  /**
    153   * Convert the handle to a read-only handle.
    154   *
    155   * Note that this doesn't enforce any sort of security or guarantees on the
    156   * underlying shared memory.
    157   */
    158  ReadOnlyHandle ToReadOnly() &&;
    159 
    160  /**
    161   * Use the handle as a read-only handle.
    162   *
    163   * Note that this doesn't enforce any sort of security or guarantees on the
    164   * underlying shared memory.
    165   */
    166  const ReadOnlyHandle& AsReadOnly() const;
    167 
    168  /**
    169   * Map the shared memory region into memory.
    170   */
    171  MutableMapping Map(void* aFixedAddress = nullptr) const;
    172 
    173  /**
    174   * Map a subregion of the shared memory region into memory.
    175   */
    176  MutableMapping MapSubregion(uint64_t aOffset, size_t aSize,
    177                              void* aFixedAddress = nullptr) const;
    178 
    179  /**
    180   * Map the shared memory region into memory, keeping the handle with it.
    181   */
    182  MutableMappingWithHandle MapWithHandle(void* aFixedAddress = nullptr) &&;
    183 };
    184 
    185 /**
    186 * A read-only handle to a shared memory region.
    187 */
    188 template <>
    189 struct Handle<Type::ReadOnly> : HandleBase {
    190  /**
    191   * Create an empty ReadOnlyHandle.
    192   */
    193  Handle() = default;
    194  MOZ_IMPLICIT Handle(std::nullptr_t) {}
    195 
    196  /**
    197   * Clone the handle.
    198   */
    199  Handle Clone() const { return CloneAs<Type::ReadOnly>(); }
    200 
    201  /**
    202   * Map the shared memory region into memory.
    203   */
    204  ReadOnlyMapping Map(void* aFixedAddress = nullptr) const;
    205 
    206  /**
    207   * Map a subregion of the shared memory region into memory.
    208   */
    209  ReadOnlyMapping MapSubregion(uint64_t aOffset, size_t aSize,
    210                               void* aFixedAddress = nullptr) const;
    211 
    212  /**
    213   * Map the shared memory region into memory, keeping the handle with it.
    214   */
    215  ReadOnlyMappingWithHandle MapWithHandle(void* aFixedAddress = nullptr) &&;
    216 };
    217 
    218 /**
    219 * A freezable handle to a shared memory region.
    220 *
    221 * One cannot clone this handle, ensuring that at most one writable mapping
    222 * exists. After freezing, no new writable mappings can be created.
    223 */
    224 template <>
    225 struct Handle<Type::Freezable> : HandleBase {
    226  /**
    227   * Create an empty FreezableHandle.
    228   */
    229  Handle() = default;
    230  MOZ_IMPLICIT Handle(std::nullptr_t) {}
    231  ~Handle();
    232 
    233  Handle(Handle&&) = default;
    234  Handle& operator=(Handle&&) = default;
    235 
    236  /**
    237   * Convert to a normal handle if we will not freeze this handle.
    238   */
    239  MutableHandle WontFreeze() &&;
    240 
    241  /**
    242   * Freeze this handle, returning a read-only handle.
    243   */
    244  ReadOnlyHandle Freeze() &&;
    245 
    246  /**
    247   * Map the shared memory region into memory.
    248   */
    249  FreezableMapping Map(void* aFixedAddress = nullptr) &&;
    250 
    251  /**
    252   * Map a subregion of the shared memory region into memory.
    253   */
    254  FreezableMapping MapSubregion(uint64_t aOffset, size_t aSize,
    255                                void* aFixedAddress = nullptr) &&;
    256 
    257  friend class Platform;
    258 #if !defined(XP_DARWIN) && !defined(XP_WIN) && !defined(ANDROID)
    259 private:
    260  PlatformHandle mFrozenFile;
    261 #endif
    262 };
    263 
    264 /**
    265 * Create a new shared memory region.
    266 */
    267 MutableHandle Create(uint64_t aSize);
    268 
    269 /**
    270 * Create a new freezable shared memory region.
    271 *
    272 * Freezable shared memory regions are distinguished by the property that there
    273 * is guaranteed to be at most one writable mapping of the region at a time.
    274 *
    275 * Furthermore, a freezable shared memory region can be frozen while mapped. In
    276 * this case, the mapping remains valid but there can be no new writable
    277 * mappings.
    278 */
    279 FreezableHandle CreateFreezable(uint64_t aSize);
    280 
    281 #if defined(XP_LINUX)
    282 // If named POSIX shm is being used, append the prefix (including
    283 // the leading '/') that would be used by a process with the given
    284 // pid to the given string and return true.  If not, return false.
    285 // (This is public so that the Linux sandboxing code can use it.)
    286 bool AppendPosixShmPrefix(std::string* str, pid_t pid);
    287 
    288 // Returns whether POSIX shm is in use.
    289 bool UsingPosixShm();
    290 #endif
    291 
    292 }  // namespace shared_memory
    293 
    294 using MutableSharedMemoryHandle = shared_memory::MutableHandle;
    295 using ReadOnlySharedMemoryHandle = shared_memory::ReadOnlyHandle;
    296 using FreezableSharedMemoryHandle = shared_memory::FreezableHandle;
    297 
    298 }  // namespace mozilla::ipc
    299 
    300 namespace IPC {
    301 
    302 template <>
    303 struct ParamTraits<mozilla::ipc::shared_memory::MutableHandle> {
    304  static void Write(MessageWriter* aWriter,
    305                    mozilla::ipc::shared_memory::MutableHandle&& aParam);
    306  static bool Read(MessageReader* aReader,
    307                   mozilla::ipc::shared_memory::MutableHandle* aResult);
    308 };
    309 
    310 template <>
    311 struct ParamTraits<mozilla::ipc::shared_memory::ReadOnlyHandle> {
    312  static void Write(MessageWriter* aWriter,
    313                    mozilla::ipc::shared_memory::ReadOnlyHandle&& aParam);
    314  static bool Read(MessageReader* aReader,
    315                   mozilla::ipc::shared_memory::ReadOnlyHandle* aResult);
    316 };
    317 
    318 }  // namespace IPC
    319 
    320 #endif