• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "base/memory/platform_shared_memory_region.h"
6 
7 #include "base/bits.h"
8 #include "base/memory/aligned_memory.h"
9 #include "base/memory/shared_memory_mapping.h"
10 #include "base/memory/shared_memory_security_policy.h"
11 #include "base/metrics/histogram_functions.h"
12 #include "base/numerics/checked_math.h"
13 #include "base/system/sys_info.h"
14 
15 namespace base {
16 namespace subtle {
17 
18 // static
CreateWritable(size_t size)19 PlatformSharedMemoryRegion PlatformSharedMemoryRegion::CreateWritable(
20     size_t size) {
21   return Create(Mode::kWritable, size);
22 }
23 
24 // static
CreateUnsafe(size_t size)25 PlatformSharedMemoryRegion PlatformSharedMemoryRegion::CreateUnsafe(
26     size_t size) {
27   return Create(Mode::kUnsafe, size);
28 }
29 
30 PlatformSharedMemoryRegion::PlatformSharedMemoryRegion() = default;
31 PlatformSharedMemoryRegion::PlatformSharedMemoryRegion(
32     PlatformSharedMemoryRegion&& other) = default;
33 PlatformSharedMemoryRegion& PlatformSharedMemoryRegion::operator=(
34     PlatformSharedMemoryRegion&& other) = default;
35 PlatformSharedMemoryRegion::~PlatformSharedMemoryRegion() = default;
36 
37 ScopedPlatformSharedMemoryHandle
PassPlatformHandle()38 PlatformSharedMemoryRegion::PassPlatformHandle() {
39   return std::move(handle_);
40 }
41 
MapAt(uint64_t offset,size_t size,SharedMemoryMapper * mapper) const42 absl::optional<span<uint8_t>> PlatformSharedMemoryRegion::MapAt(
43     uint64_t offset,
44     size_t size,
45     SharedMemoryMapper* mapper) const {
46   if (!IsValid())
47     return absl::nullopt;
48 
49   if (size == 0)
50     return absl::nullopt;
51 
52   size_t end_byte;
53   if (!CheckAdd(offset, size).AssignIfValid(&end_byte) || end_byte > size_) {
54     return absl::nullopt;
55   }
56 
57   // TODO(dcheng): Presumably the actual size of the mapping is rounded to
58   // `SysInfo::VMAllocationGranularity()`. Should this accounting be done with
59   // that in mind?
60   if (!SharedMemorySecurityPolicy::AcquireReservationForMapping(size)) {
61     return absl::nullopt;
62   }
63 
64   if (!mapper)
65     mapper = SharedMemoryMapper::GetDefaultInstance();
66 
67   // The backing mapper expects offset to be aligned to
68   // `SysInfo::VMAllocationGranularity()`.
69   uint64_t aligned_offset =
70       bits::AlignDown(offset, uint64_t{SysInfo::VMAllocationGranularity()});
71   size_t adjustment_for_alignment =
72       static_cast<size_t>(offset - aligned_offset);
73 
74   bool write_allowed = mode_ != Mode::kReadOnly;
75   auto result = mapper->Map(GetPlatformHandle(), write_allowed, aligned_offset,
76                             size + adjustment_for_alignment);
77 
78   if (result.has_value()) {
79     DCHECK(IsAligned(result.value().data(), kMapMinimumAlignment));
80     if (offset != 0) {
81       // Undo the previous adjustment so the returned mapping respects the exact
82       // requested `offset` and `size`.
83       result = result->subspan(adjustment_for_alignment);
84     }
85   } else {
86     SharedMemorySecurityPolicy::ReleaseReservationForMapping(size);
87   }
88 
89   return result;
90 }
91 
Unmap(span<uint8_t> mapping,SharedMemoryMapper * mapper)92 void PlatformSharedMemoryRegion::Unmap(span<uint8_t> mapping,
93                                        SharedMemoryMapper* mapper) {
94   if (!mapper) {
95     mapper = SharedMemoryMapper::GetDefaultInstance();
96   }
97 
98   mapper->Unmap(mapping);
99 
100   SharedMemorySecurityPolicy::ReleaseReservationForMapping(mapping.size());
101 }
102 
103 }  // namespace subtle
104 }  // namespace base
105