blob: 5f706fe648598642584903f39a5aa40786acc88d [file] [log] [blame]
[email protected]b05df6b2011-12-01 23:19:311// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
[email protected]99873aa2013-03-29 17:46:235#include "base/memory/shared_memory.h"
initial.commitd7cae122008-07-26 21:49:386
[email protected]6d6797eb2014-08-07 22:07:437#include <aclapi.h>
8
initial.commitd7cae122008-07-26 21:49:389#include "base/logging.h"
[email protected]6d6797eb2014-08-07 22:07:4310#include "base/memory/scoped_ptr.h"
[email protected]dc84fcc2014-07-24 11:42:5911#include "base/rand_util.h"
12#include "base/strings/stringprintf.h"
[email protected]a4ea1f12013-06-07 18:37:0713#include "base/strings/utf_string_conversions.h"
initial.commitd7cae122008-07-26 21:49:3814
[email protected]67ea5072013-03-28 02:02:1815namespace {
16
17// Returns the length of the memory section starting at the supplied address.
18size_t GetMemorySectionSize(void* address) {
19 MEMORY_BASIC_INFORMATION memory_info;
20 if (!::VirtualQuery(address, &memory_info, sizeof(memory_info)))
21 return 0;
22 return memory_info.RegionSize - (static_cast<char*>(address) -
23 static_cast<char*>(memory_info.AllocationBase));
24}
25
26} // namespace.
27
[email protected]176aa482008-11-14 03:25:1528namespace base {
29
initial.commitd7cae122008-07-26 21:49:3830SharedMemory::SharedMemory()
31 : mapped_file_(NULL),
sammc5648c852015-07-02 01:25:0032 mapped_size_(0),
initial.commitd7cae122008-07-26 21:49:3833 memory_(NULL),
34 read_only_(false),
erikchen893dadc62015-06-18 21:48:3335 requested_size_(0) {
initial.commitd7cae122008-07-26 21:49:3836}
37
[email protected]8cc41942010-11-05 19:16:0738SharedMemory::SharedMemory(const std::wstring& name)
sammc5648c852015-07-02 01:25:0039 : name_(name),
40 mapped_file_(NULL),
41 mapped_size_(0),
[email protected]8cc41942010-11-05 19:16:0742 memory_(NULL),
43 read_only_(false),
sammc5648c852015-07-02 01:25:0044 requested_size_(0) {
[email protected]8cc41942010-11-05 19:16:0745}
46
scottmgd19b4f72015-06-19 22:51:0047SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
initial.commitd7cae122008-07-26 21:49:3848 : mapped_file_(handle),
sammc5648c852015-07-02 01:25:0049 mapped_size_(0),
initial.commitd7cae122008-07-26 21:49:3850 memory_(NULL),
51 read_only_(read_only),
sammc5648c852015-07-02 01:25:0052 requested_size_(0) {
initial.commitd7cae122008-07-26 21:49:3853}
54
scottmgd19b4f72015-06-19 22:51:0055SharedMemory::SharedMemory(const SharedMemoryHandle& handle,
erikchen893dadc62015-06-18 21:48:3356 bool read_only,
initial.commitd7cae122008-07-26 21:49:3857 ProcessHandle process)
58 : mapped_file_(NULL),
sammc5648c852015-07-02 01:25:0059 mapped_size_(0),
initial.commitd7cae122008-07-26 21:49:3860 memory_(NULL),
61 read_only_(read_only),
sammc5648c852015-07-02 01:25:0062 requested_size_(0) {
initial.commitd7cae122008-07-26 21:49:3863 ::DuplicateHandle(process, handle,
64 GetCurrentProcess(), &mapped_file_,
[email protected]5c744612013-10-30 15:17:0565 read_only_ ? FILE_MAP_READ : FILE_MAP_READ |
66 FILE_MAP_WRITE,
initial.commitd7cae122008-07-26 21:49:3867 FALSE, 0);
68}
69
70SharedMemory::~SharedMemory() {
jbauman569918b2014-12-10 22:07:2071 Unmap();
initial.commitd7cae122008-07-26 21:49:3872 Close();
initial.commitd7cae122008-07-26 21:49:3873}
74
[email protected]5fe733de2009-02-11 18:59:2075// static
76bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
77 return handle != NULL;
78}
79
[email protected]76aac1e2009-03-16 16:45:3680// static
81SharedMemoryHandle SharedMemory::NULLHandle() {
82 return NULL;
83}
84
[email protected]b0af04c2009-05-18 17:46:3185// static
86void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) {
87 DCHECK(handle != NULL);
88 ::CloseHandle(handle);
89}
90
[email protected]c14eda92013-05-09 23:15:4091// static
92size_t SharedMemory::GetHandleLimit() {
93 // Rounded down from value reported here:
94 // http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx
95 return static_cast<size_t>(1 << 23);
96}
97
erikchen2096f622015-06-03 00:26:5998// static
99SharedMemoryHandle SharedMemory::DuplicateHandle(
erikchen8539d852015-05-30 01:49:19100 const SharedMemoryHandle& handle) {
erikchen2096f622015-06-03 00:26:59101 ProcessHandle process = GetCurrentProcess();
102 SharedMemoryHandle duped_handle;
103 BOOL success = ::DuplicateHandle(process, handle, process, &duped_handle, 0,
104 FALSE, DUPLICATE_SAME_ACCESS);
105 if (success)
106 return duped_handle;
107 return NULLHandle();
erikchen8539d852015-05-30 01:49:19108}
109
[email protected]374f1a82013-01-10 02:16:24110bool SharedMemory::CreateAndMapAnonymous(size_t size) {
[email protected]54e3dfa22010-10-27 18:16:06111 return CreateAnonymous(size) && Map(size);
112}
113
[email protected]b05df6b2011-12-01 23:19:31114bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
[email protected]67ea5072013-03-28 02:02:18115 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here,
116 // wasting 32k per mapping on average.
117 static const size_t kSectionMask = 65536 - 1;
[email protected]b05df6b2011-12-01 23:19:31118 DCHECK(!options.executable);
[email protected]5d2b4492011-03-01 02:48:05119 DCHECK(!mapped_file_);
[email protected]b05df6b2011-12-01 23:19:31120 if (options.size == 0)
[email protected]54e3dfa22010-10-27 18:16:06121 return false;
initial.commitd7cae122008-07-26 21:49:38122
[email protected]67ea5072013-03-28 02:02:18123 // Check maximum accounting for overflow.
124 if (options.size >
125 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask)
[email protected]374f1a82013-01-10 02:16:24126 return false;
127
[email protected]67ea5072013-03-28 02:02:18128 size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask;
thestig8badc792014-12-04 22:14:22129 name_ = options.name_deprecated ?
130 ASCIIToUTF16(*options.name_deprecated) : L"";
[email protected]6d6797eb2014-08-07 22:07:43131 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE };
132 SECURITY_DESCRIPTOR sd;
133 ACL dacl;
134
[email protected]dc84fcc2014-07-24 11:42:59135 if (options.share_read_only && name_.empty()) {
[email protected]6d6797eb2014-08-07 22:07:43136 // Add an empty DACL to enforce anonymous read-only sections.
137 sa.lpSecurityDescriptor = &sd;
138 if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION))
139 return false;
140 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
141 return false;
142 if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE))
143 return false;
144
[email protected]dc84fcc2014-07-24 11:42:59145 // Windows ignores DACLs on certain unnamed objects (like shared sections).
146 // So, we generate a random name when we need to enforce read-only.
147 uint64_t rand_values[4];
thestig8badc792014-12-04 22:14:22148 RandBytes(&rand_values, sizeof(rand_values));
149 name_ = StringPrintf(L"CrSharedMem_%016x%016x%016x%016x",
150 rand_values[0], rand_values[1],
151 rand_values[2], rand_values[3]);
[email protected]dc84fcc2014-07-24 11:42:59152 }
[email protected]6d6797eb2014-08-07 22:07:43153 mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, &sa,
shrikant9426fb82015-02-24 00:27:33154 PAGE_READWRITE, 0, static_cast<DWORD>(rounded_size),
155 name_.empty() ? nullptr : name_.c_str());
initial.commitd7cae122008-07-26 21:49:38156 if (!mapped_file_)
157 return false;
158
[email protected]67ea5072013-03-28 02:02:18159 requested_size_ = options.size;
[email protected]54e3dfa22010-10-27 18:16:06160
initial.commitd7cae122008-07-26 21:49:38161 // Check if the shared memory pre-exists.
[email protected]54e3dfa22010-10-27 18:16:06162 if (GetLastError() == ERROR_ALREADY_EXISTS) {
[email protected]67ea5072013-03-28 02:02:18163 // If the file already existed, set requested_size_ to 0 to show that
[email protected]54e3dfa22010-10-27 18:16:06164 // we don't know the size.
[email protected]67ea5072013-03-28 02:02:18165 requested_size_ = 0;
[email protected]ff672b72014-03-05 21:13:52166 if (!options.open_existing_deprecated) {
[email protected]54e3dfa22010-10-27 18:16:06167 Close();
168 return false;
169 }
initial.commitd7cae122008-07-26 21:49:38170 }
[email protected]54e3dfa22010-10-27 18:16:06171
initial.commitd7cae122008-07-26 21:49:38172 return true;
173}
174
[email protected]b6413b49b2010-09-29 20:32:22175bool SharedMemory::Delete(const std::string& name) {
[email protected]9e51af92009-02-04 00:58:39176 // intentionally empty -- there is nothing for us to do on Windows.
177 return true;
178}
179
[email protected]b6413b49b2010-09-29 20:32:22180bool SharedMemory::Open(const std::string& name, bool read_only) {
[email protected]5d2b4492011-03-01 02:48:05181 DCHECK(!mapped_file_);
initial.commitd7cae122008-07-26 21:49:38182
thestig8badc792014-12-04 22:14:22183 name_ = ASCIIToUTF16(name);
initial.commitd7cae122008-07-26 21:49:38184 read_only_ = read_only;
185 mapped_file_ = OpenFileMapping(
[email protected]5c744612013-10-30 15:17:05186 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE,
187 false, name_.empty() ? NULL : name_.c_str());
initial.commitd7cae122008-07-26 21:49:38188 if (mapped_file_ != NULL) {
189 // Note: size_ is not set in this case.
190 return true;
191 }
192 return false;
193}
194
[email protected]e29e3f552013-01-16 09:02:34195bool SharedMemory::MapAt(off_t offset, size_t bytes) {
initial.commitd7cae122008-07-26 21:49:38196 if (mapped_file_ == NULL)
197 return false;
198
[email protected]374f1a82013-01-10 02:16:24199 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max()))
200 return false;
201
[email protected]421c1502014-03-18 22:33:28202 if (memory_)
203 return false;
204
initial.commitd7cae122008-07-26 21:49:38205 memory_ = MapViewOfFile(mapped_file_,
[email protected]5c744612013-10-30 15:17:05206 read_only_ ? FILE_MAP_READ : FILE_MAP_READ |
207 FILE_MAP_WRITE,
[email protected]e29e3f552013-01-16 09:02:34208 static_cast<uint64>(offset) >> 32,
209 static_cast<DWORD>(offset),
210 bytes);
initial.commitd7cae122008-07-26 21:49:38211 if (memory_ != NULL) {
[email protected]404a0582012-08-18 02:17:26212 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
213 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
[email protected]67ea5072013-03-28 02:02:18214 mapped_size_ = GetMemorySectionSize(memory_);
initial.commitd7cae122008-07-26 21:49:38215 return true;
216 }
217 return false;
218}
219
220bool SharedMemory::Unmap() {
221 if (memory_ == NULL)
222 return false;
223
224 UnmapViewOfFile(memory_);
225 memory_ = NULL;
226 return true;
227}
228
229bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
thestig8badc792014-12-04 22:14:22230 SharedMemoryHandle* new_handle,
[email protected]5f58adab2013-11-20 23:41:25231 bool close_self,
232 ShareMode share_mode) {
initial.commitd7cae122008-07-26 21:49:38233 *new_handle = 0;
[email protected]5c744612013-10-30 15:17:05234 DWORD access = FILE_MAP_READ;
initial.commitd7cae122008-07-26 21:49:38235 DWORD options = 0;
236 HANDLE mapped_file = mapped_file_;
237 HANDLE result;
[email protected]5f58adab2013-11-20 23:41:25238 if (share_mode == SHARE_CURRENT_MODE && !read_only_)
initial.commitd7cae122008-07-26 21:49:38239 access |= FILE_MAP_WRITE;
240 if (close_self) {
241 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file.
242 options = DUPLICATE_CLOSE_SOURCE;
243 mapped_file_ = NULL;
244 Unmap();
245 }
246
247 if (process == GetCurrentProcess() && close_self) {
248 *new_handle = mapped_file;
249 return true;
250 }
251
erikchen2096f622015-06-03 00:26:59252 if (!::DuplicateHandle(GetCurrentProcess(), mapped_file, process, &result,
253 access, FALSE, options)) {
initial.commitd7cae122008-07-26 21:49:38254 return false;
erikchen2096f622015-06-03 00:26:59255 }
initial.commitd7cae122008-07-26 21:49:38256 *new_handle = result;
257 return true;
258}
259
260
261void SharedMemory::Close() {
initial.commitd7cae122008-07-26 21:49:38262 if (mapped_file_ != NULL) {
263 CloseHandle(mapped_file_);
264 mapped_file_ = NULL;
265 }
266}
267
[email protected]5fe733de2009-02-11 18:59:20268SharedMemoryHandle SharedMemory::handle() const {
269 return mapped_file_;
270}
271
[email protected]176aa482008-11-14 03:25:15272} // namespace base