tor-browser

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

shared_memory_mapping.h (9237B)


      1 // Copyright 2018 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_MEMORY_SHARED_MEMORY_MAPPING_H_
      6 #define BASE_MEMORY_SHARED_MEMORY_MAPPING_H_
      7 
      8 #include <cstddef>
      9 #include <type_traits>
     10 
     11 #include "base/base_export.h"
     12 #include "base/check.h"
     13 #include "base/containers/span.h"
     14 #include "base/memory/raw_ptr.h"
     15 #include "base/memory/shared_memory_mapper.h"
     16 #include "base/unguessable_token.h"
     17 
     18 namespace base {
     19 
     20 namespace subtle {
     21 class PlatformSharedMemoryRegion;
     22 }  // namespace subtle
     23 
     24 // Base class for scoped handles to a shared memory mapping created from a
     25 // shared memory region. Created shared memory mappings remain valid even if the
     26 // creator region is transferred or destroyed.
     27 //
     28 // Each mapping has an UnguessableToken that identifies the shared memory region
     29 // it was created from. This is used for memory metrics, to avoid overcounting
     30 // shared memory.
     31 class BASE_EXPORT SharedMemoryMapping {
     32 public:
     33  // Default constructor initializes an invalid instance.
     34  SharedMemoryMapping();
     35 
     36  // Move operations are allowed.
     37  SharedMemoryMapping(SharedMemoryMapping&& mapping) noexcept;
     38  SharedMemoryMapping& operator=(SharedMemoryMapping&& mapping) noexcept;
     39 
     40  SharedMemoryMapping(const SharedMemoryMapping&) = delete;
     41  SharedMemoryMapping& operator=(const SharedMemoryMapping&) = delete;
     42 
     43  // Unmaps the region if the mapping is valid.
     44  virtual ~SharedMemoryMapping();
     45 
     46  // Returns true iff the mapping is valid. False means there is no
     47  // corresponding area of memory.
     48  bool IsValid() const { return !mapped_span_.empty(); }
     49 
     50  // Returns the logical size of the mapping in bytes. This is precisely the
     51  // size requested by whoever created the mapping, and it is always less than
     52  // or equal to |mapped_size()|. This is undefined for invalid instances.
     53  size_t size() const {
     54    DCHECK(IsValid());
     55    return size_;
     56  }
     57 
     58  // Returns the actual size of the mapping in bytes. This is always at least
     59  // as large as |size()| but may be larger due to platform mapping alignment
     60  // constraints. This is undefined for invalid instances.
     61  size_t mapped_size() const {
     62    DCHECK(IsValid());
     63    return mapped_span_.size();
     64  }
     65 
     66  // Returns 128-bit GUID of the region this mapping belongs to.
     67  const UnguessableToken& guid() const {
     68    DCHECK(IsValid());
     69    return guid_;
     70  }
     71 
     72 protected:
     73  SharedMemoryMapping(span<uint8_t> mapped_span,
     74                      size_t size,
     75                      const UnguessableToken& guid,
     76                      SharedMemoryMapper* mapper);
     77  void* raw_memory_ptr() const {
     78    return reinterpret_cast<void*>(mapped_span_.data());
     79  }
     80 
     81 private:
     82  friend class SharedMemoryTracker;
     83 
     84  void Unmap();
     85 
     86  span<uint8_t> mapped_span_;
     87  size_t size_ = 0;
     88  UnguessableToken guid_;
     89  raw_ptr<SharedMemoryMapper> mapper_ = nullptr;
     90 };
     91 
     92 // Class modeling a read-only mapping of a shared memory region into the
     93 // current process' address space. This is created by ReadOnlySharedMemoryRegion
     94 // instances.
     95 class BASE_EXPORT ReadOnlySharedMemoryMapping : public SharedMemoryMapping {
     96 public:
     97  // Default constructor initializes an invalid instance.
     98  ReadOnlySharedMemoryMapping();
     99 
    100  ReadOnlySharedMemoryMapping(const ReadOnlySharedMemoryMapping&) = delete;
    101  ReadOnlySharedMemoryMapping& operator=(const ReadOnlySharedMemoryMapping&) =
    102      delete;
    103 
    104  // Move operations are allowed.
    105  ReadOnlySharedMemoryMapping(ReadOnlySharedMemoryMapping&&) noexcept;
    106  ReadOnlySharedMemoryMapping& operator=(
    107      ReadOnlySharedMemoryMapping&&) noexcept;
    108 
    109  // Returns the base address of the read-only mapping. Returns nullptr for
    110  // invalid instances.
    111  const void* memory() const { return raw_memory_ptr(); }
    112 
    113  // Returns a pointer to a page-aligned const T if the mapping is valid and
    114  // large enough to contain a T, or nullptr otherwise.
    115  template <typename T>
    116  const T* GetMemoryAs() const {
    117    static_assert(std::is_trivially_copyable_v<T>,
    118                  "Copying non-trivially-copyable object across memory spaces "
    119                  "is dangerous");
    120    if (!IsValid())
    121      return nullptr;
    122    if (sizeof(T) > size())
    123      return nullptr;
    124    return static_cast<const T*>(raw_memory_ptr());
    125  }
    126 
    127  // Returns a span of const T. The number of elements is autodeduced from the
    128  // size of the shared memory mapping. The number of elements may be
    129  // autodeduced as zero, i.e. the mapping is invalid or the size of the mapping
    130  // isn't large enough to contain even one T: in that case, an empty span
    131  // will be returned. The first element, if any, is guaranteed to be
    132  // page-aligned.
    133  template <typename T>
    134  span<const T> GetMemoryAsSpan() const {
    135    static_assert(std::is_trivially_copyable_v<T>,
    136                  "Copying non-trivially-copyable object across memory spaces "
    137                  "is dangerous");
    138    if (!IsValid())
    139      return span<const T>();
    140    size_t count = size() / sizeof(T);
    141    return GetMemoryAsSpan<T>(count);
    142  }
    143 
    144  // Returns a span of const T with |count| elements if the mapping is valid and
    145  // large enough to contain |count| elements, or an empty span otherwise. The
    146  // first element, if any, is guaranteed to be page-aligned.
    147  template <typename T>
    148  span<const T> GetMemoryAsSpan(size_t count) const {
    149    static_assert(std::is_trivially_copyable_v<T>,
    150                  "Copying non-trivially-copyable object across memory spaces "
    151                  "is dangerous");
    152    if (!IsValid())
    153      return span<const T>();
    154    if (size() / sizeof(T) < count)
    155      return span<const T>();
    156    return span<const T>(static_cast<const T*>(raw_memory_ptr()), count);
    157  }
    158 
    159 private:
    160  friend class ReadOnlySharedMemoryRegion;
    161  ReadOnlySharedMemoryMapping(span<uint8_t> mapped_span,
    162                              size_t size,
    163                              const UnguessableToken& guid,
    164                              SharedMemoryMapper* mapper);
    165 };
    166 
    167 // Class modeling a writable mapping of a shared memory region into the
    168 // current process' address space. This is created by *SharedMemoryRegion
    169 // instances.
    170 class BASE_EXPORT WritableSharedMemoryMapping : public SharedMemoryMapping {
    171 public:
    172  // Default constructor initializes an invalid instance.
    173  WritableSharedMemoryMapping();
    174 
    175  WritableSharedMemoryMapping(const WritableSharedMemoryMapping&) = delete;
    176  WritableSharedMemoryMapping& operator=(const WritableSharedMemoryMapping&) =
    177      delete;
    178 
    179  // Move operations are allowed.
    180  WritableSharedMemoryMapping(WritableSharedMemoryMapping&&) noexcept;
    181  WritableSharedMemoryMapping& operator=(
    182      WritableSharedMemoryMapping&&) noexcept;
    183 
    184  // Returns the base address of the writable mapping. Returns nullptr for
    185  // invalid instances.
    186  void* memory() const { return raw_memory_ptr(); }
    187 
    188  // Returns a pointer to a page-aligned T if the mapping is valid and large
    189  // enough to contain a T, or nullptr otherwise.
    190  template <typename T>
    191  T* GetMemoryAs() const {
    192    static_assert(std::is_trivially_copyable_v<T>,
    193                  "Copying non-trivially-copyable object across memory spaces "
    194                  "is dangerous");
    195    if (!IsValid())
    196      return nullptr;
    197    if (sizeof(T) > size())
    198      return nullptr;
    199    return static_cast<T*>(raw_memory_ptr());
    200  }
    201 
    202  // Returns a span of T. The number of elements is autodeduced from the size of
    203  // the shared memory mapping. The number of elements may be autodeduced as
    204  // zero, i.e. the mapping is invalid or the size of the mapping isn't large
    205  // enough to contain even one T: in that case, an empty span will be returned.
    206  // The first element, if any, is guaranteed to be page-aligned.
    207  template <typename T>
    208  span<T> GetMemoryAsSpan() const {
    209    static_assert(std::is_trivially_copyable_v<T>,
    210                  "Copying non-trivially-copyable object across memory spaces "
    211                  "is dangerous");
    212    if (!IsValid())
    213      return span<T>();
    214    size_t count = size() / sizeof(T);
    215    return GetMemoryAsSpan<T>(count);
    216  }
    217 
    218  // Returns a span of T with |count| elements if the mapping is valid and large
    219  // enough to contain |count| elements, or an empty span otherwise. The first
    220  // element, if any, is guaranteed to be page-aligned.
    221  template <typename T>
    222  span<T> GetMemoryAsSpan(size_t count) const {
    223    static_assert(std::is_trivially_copyable_v<T>,
    224                  "Copying non-trivially-copyable object across memory spaces "
    225                  "is dangerous");
    226    if (!IsValid())
    227      return span<T>();
    228    if (size() / sizeof(T) < count)
    229      return span<T>();
    230    return span<T>(static_cast<T*>(raw_memory_ptr()), count);
    231  }
    232 
    233 private:
    234  friend WritableSharedMemoryMapping MapAtForTesting(
    235      subtle::PlatformSharedMemoryRegion* region,
    236      uint64_t offset,
    237      size_t size);
    238  friend class ReadOnlySharedMemoryRegion;
    239  friend class WritableSharedMemoryRegion;
    240  friend class UnsafeSharedMemoryRegion;
    241  WritableSharedMemoryMapping(span<uint8_t> mapped_span,
    242                              size_t size,
    243                              const UnguessableToken& guid,
    244                              SharedMemoryMapper* mapper);
    245 };
    246 
    247 }  // namespace base
    248 
    249 #endif  // BASE_MEMORY_SHARED_MEMORY_MAPPING_H_