1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
base / memory / writable_shared_memory_region.h [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_
#define BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_
#include <stdint.h>
#include "base/base_export.h"
#include "base/check.h"
#include "base/compiler_specific.h"
#include "base/memory/platform_shared_memory_region.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "build/build_config.h"
namespace base {
// Scoped move-only handle to a region of platform shared memory. The instance
// owns the platform handle it wraps. Mappings created by this region are
// writable. These mappings remain valid even after the region handle is moved
// or destroyed.
//
// This region can be locked to read-only access by converting it to a
// ReadOnlySharedMemoryRegion. However, unlike ReadOnlySharedMemoryRegion and
// UnsafeSharedMemoryRegion, ownership of this region (while writable) is unique
// and may only be transferred, not duplicated.
//
// Unlike ReadOnlySharedMemoryRegion and UnsafeSharedMemoryRegion,
// WritableSharedMemoryRegion doesn't provide GetPlatformHandle() method to
// ensure that the region is never duplicated while writable.
class BASE_EXPORT WritableSharedMemoryRegion {
public:
using MappingType = WritableSharedMemoryMapping;
// Creates a new WritableSharedMemoryRegion instance of a given
// size that can be used for mapping writable shared memory into the virtual
// address space.
static WritableSharedMemoryRegion Create(size_t size);
using CreateFunction = decltype(Create);
// Returns a WritableSharedMemoryRegion built from a platform handle that was
// taken from another WritableSharedMemoryRegion instance. Returns an invalid
// region iff the |handle| is invalid. CHECK-fails if the |handle| isn't
// writable.
// This should be used only by the code passing handles across process
// boundaries.
static WritableSharedMemoryRegion Deserialize(
subtle::PlatformSharedMemoryRegion handle);
// Extracts a platform handle from the region. Ownership is transferred to the
// returned region object.
// This should be used only for sending the handle from the current
// process to another.
static subtle::PlatformSharedMemoryRegion TakeHandleForSerialization(
WritableSharedMemoryRegion region);
// Makes the region read-only. No new writable mappings of the region can be
// created after this call. Returns an invalid region on failure.
static ReadOnlySharedMemoryRegion ConvertToReadOnly(
WritableSharedMemoryRegion region);
// Makes the region unsafe. The region cannot be converted to read-only after
// this call. Returns an invalid region on failure.
static UnsafeSharedMemoryRegion ConvertToUnsafe(
WritableSharedMemoryRegion region);
// Default constructor initializes an invalid instance.
WritableSharedMemoryRegion();
// Move operations are allowed.
WritableSharedMemoryRegion(WritableSharedMemoryRegion&&);
WritableSharedMemoryRegion& operator=(WritableSharedMemoryRegion&&);
WritableSharedMemoryRegion(const WritableSharedMemoryRegion&) = delete;
WritableSharedMemoryRegion& operator=(const WritableSharedMemoryRegion&) =
delete;
// Destructor closes shared memory region if valid.
// All created mappings will remain valid.
~WritableSharedMemoryRegion();
// Maps the shared memory region into the caller's address space with write
// access. The mapped address is guaranteed to have an alignment of
// at least |subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment|.
// Returns a valid WritableSharedMemoryMapping instance on success, invalid
// otherwise. A custom |SharedMemoryMapper| for mapping (and later unmapping)
// the region can be provided using the optional |mapper| parameter.
WritableSharedMemoryMapping Map(SharedMemoryMapper* mapper = nullptr) const;
// Similar to `Map()`, but maps only `size` bytes of the shared memory block
// at byte `offset`. Returns an invalid mapping if requested bytes are out of
// the region limits.
//
// `offset` does not need to be aligned; if `offset` is not a multiple of
// `subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment`, then the
// returned mapping will not respect alignment either. Internally, `offset`
// and `size` are still first adjusted to respect alignment when mapping in
// the shared memory region, but the returned mapping will be "unadjusted" to
// match the exact `offset` and `size` requested.
WritableSharedMemoryMapping MapAt(uint64_t offset,
size_t size,
SharedMemoryMapper* mapper = nullptr) const;
// Whether underlying platform handles are valid.
bool IsValid() const;
// Returns the maximum mapping size that can be created from this region.
size_t GetSize() const {
DCHECK(IsValid());
return handle_.GetSize();
}
// Returns 128-bit GUID of the region.
const UnguessableToken& GetGUID() const LIFETIME_BOUND {
DCHECK(IsValid());
return handle_.GetGUID();
}
#if BUILDFLAG(IS_WIN)
// On Windows it is necessary in rare cases to take a writable handle from a
// region that will be converted to read-only. On this platform it is a safe
// operation, as the handle returned from this method will remain writable
// after the region is converted to read-only. However, it breaks chromium's
// WritableSharedMemoryRegion semantics and so should be use with care.
HANDLE UnsafeGetPlatformHandle() const { return handle_.GetPlatformHandle(); }
#endif
private:
friend class SharedMemoryHooks;
explicit WritableSharedMemoryRegion(
subtle::PlatformSharedMemoryRegion handle);
static void set_create_hook(CreateFunction* hook) { create_hook_ = hook; }
static CreateFunction* create_hook_;
subtle::PlatformSharedMemoryRegion handle_;
};
} // namespace base
#endif // BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_