| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 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/shared_memory.h" | |
| 6 | |
| 7 #include <aclapi.h> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "base/rand_util.h" | |
| 12 #include "base/strings/stringprintf.h" | |
| 13 #include "base/strings/utf_string_conversions.h" | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 // Returns the length of the memory section starting at the supplied address. | |
| 18 size_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 | |
| 28 namespace base { | |
| 29 | |
| 30 SharedMemory::SharedMemory() | |
| 31 : mapped_file_(NULL), | |
| 32 mapped_size_(0), | |
| 33 memory_(NULL), | |
| 34 read_only_(false), | |
| 35 requested_size_(0) {} | |
| 36 | |
| 37 SharedMemory::SharedMemory(const std::wstring& name) | |
| 38 : name_(name), | |
| 39 mapped_file_(NULL), | |
| 40 mapped_size_(0), | |
| 41 memory_(NULL), | |
| 42 read_only_(false), | |
| 43 requested_size_(0) {} | |
| 44 | |
| 45 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) | |
| 46 : mapped_file_(handle), | |
| 47 mapped_size_(0), | |
| 48 memory_(NULL), | |
| 49 read_only_(read_only), | |
| 50 requested_size_(0) {} | |
| 51 | |
| 52 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, | |
| 53 bool read_only, | |
| 54 ProcessHandle process) | |
| 55 : mapped_file_(NULL), | |
| 56 mapped_size_(0), | |
| 57 memory_(NULL), | |
| 58 read_only_(read_only), | |
| 59 requested_size_(0) { | |
| 60 ::DuplicateHandle(process, handle, | |
| 61 GetCurrentProcess(), &mapped_file_, | |
| 62 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | | |
| 63 FILE_MAP_WRITE, | |
| 64 FALSE, 0); | |
| 65 } | |
| 66 | |
| 67 SharedMemory::~SharedMemory() { | |
| 68 Unmap(); | |
| 69 Close(); | |
| 70 } | |
| 71 | |
| 72 // static | |
| 73 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { | |
| 74 return handle != NULL; | |
| 75 } | |
| 76 | |
| 77 // static | |
| 78 SharedMemoryHandle SharedMemory::NULLHandle() { | |
| 79 return NULL; | |
| 80 } | |
| 81 | |
| 82 // static | |
| 83 void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { | |
| 84 DCHECK(handle != NULL); | |
| 85 ::CloseHandle(handle); | |
| 86 } | |
| 87 | |
| 88 // static | |
| 89 size_t SharedMemory::GetHandleLimit() { | |
| 90 // Rounded down from value reported here: | |
| 91 // http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx | |
| 92 return static_cast<size_t>(1 << 23); | |
| 93 } | |
| 94 | |
| 95 // static | |
| 96 SharedMemoryHandle SharedMemory::DuplicateHandle( | |
| 97 const SharedMemoryHandle& handle) { | |
| 98 ProcessHandle process = GetCurrentProcess(); | |
| 99 SharedMemoryHandle duped_handle; | |
| 100 BOOL success = ::DuplicateHandle(process, handle, process, &duped_handle, 0, | |
| 101 FALSE, DUPLICATE_SAME_ACCESS); | |
| 102 if (success) | |
| 103 return duped_handle; | |
| 104 return NULLHandle(); | |
| 105 } | |
| 106 | |
| 107 bool SharedMemory::CreateAndMapAnonymous(size_t size) { | |
| 108 return CreateAnonymous(size) && Map(size); | |
| 109 } | |
| 110 | |
| 111 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { | |
| 112 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, | |
| 113 // wasting 32k per mapping on average. | |
| 114 static const size_t kSectionMask = 65536 - 1; | |
| 115 DCHECK(!options.executable); | |
| 116 DCHECK(!mapped_file_); | |
| 117 if (options.size == 0) | |
| 118 return false; | |
| 119 | |
| 120 // Check maximum accounting for overflow. | |
| 121 if (options.size > | |
| 122 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) | |
| 123 return false; | |
| 124 | |
| 125 size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; | |
| 126 name_ = options.name_deprecated ? | |
| 127 ASCIIToUTF16(*options.name_deprecated) : L""; | |
| 128 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE }; | |
| 129 SECURITY_DESCRIPTOR sd; | |
| 130 ACL dacl; | |
| 131 | |
| 132 if (options.share_read_only && name_.empty()) { | |
| 133 // Add an empty DACL to enforce anonymous read-only sections. | |
| 134 sa.lpSecurityDescriptor = &sd; | |
| 135 if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) | |
| 136 return false; | |
| 137 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) | |
| 138 return false; | |
| 139 if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) | |
| 140 return false; | |
| 141 | |
| 142 // Windows ignores DACLs on certain unnamed objects (like shared sections). | |
| 143 // So, we generate a random name when we need to enforce read-only. | |
| 144 uint64_t rand_values[4]; | |
| 145 RandBytes(&rand_values, sizeof(rand_values)); | |
| 146 name_ = StringPrintf(L"CrSharedMem_%016x%016x%016x%016x", | |
| 147 rand_values[0], rand_values[1], | |
| 148 rand_values[2], rand_values[3]); | |
| 149 } | |
| 150 mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, | |
| 151 PAGE_READWRITE, 0, static_cast<DWORD>(rounded_size), | |
| 152 name_.empty() ? nullptr : name_.c_str()); | |
| 153 if (!mapped_file_) | |
| 154 return false; | |
| 155 | |
| 156 requested_size_ = options.size; | |
| 157 | |
| 158 // Check if the shared memory pre-exists. | |
| 159 if (GetLastError() == ERROR_ALREADY_EXISTS) { | |
| 160 // If the file already existed, set requested_size_ to 0 to show that | |
| 161 // we don't know the size. | |
| 162 requested_size_ = 0; | |
| 163 if (!options.open_existing_deprecated) { | |
| 164 Close(); | |
| 165 return false; | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 return true; | |
| 170 } | |
| 171 | |
| 172 bool SharedMemory::Delete(const std::string& name) { | |
| 173 // intentionally empty -- there is nothing for us to do on Windows. | |
| 174 return true; | |
| 175 } | |
| 176 | |
| 177 bool SharedMemory::Open(const std::string& name, bool read_only) { | |
| 178 DCHECK(!mapped_file_); | |
| 179 | |
| 180 name_ = ASCIIToUTF16(name); | |
| 181 read_only_ = read_only; | |
| 182 mapped_file_ = OpenFileMapping( | |
| 183 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, | |
| 184 false, name_.empty() ? NULL : name_.c_str()); | |
| 185 if (mapped_file_ != NULL) { | |
| 186 // Note: size_ is not set in this case. | |
| 187 return true; | |
| 188 } | |
| 189 return false; | |
| 190 } | |
| 191 | |
| 192 bool SharedMemory::MapAt(off_t offset, size_t bytes) { | |
| 193 if (mapped_file_ == NULL) | |
| 194 return false; | |
| 195 | |
| 196 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) | |
| 197 return false; | |
| 198 | |
| 199 if (memory_) | |
| 200 return false; | |
| 201 | |
| 202 memory_ = MapViewOfFile(mapped_file_, | |
| 203 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | | |
| 204 FILE_MAP_WRITE, | |
| 205 static_cast<uint64>(offset) >> 32, | |
| 206 static_cast<DWORD>(offset), | |
| 207 bytes); | |
| 208 if (memory_ != NULL) { | |
| 209 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & | |
| 210 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); | |
| 211 mapped_size_ = GetMemorySectionSize(memory_); | |
| 212 return true; | |
| 213 } | |
| 214 return false; | |
| 215 } | |
| 216 | |
| 217 bool SharedMemory::Unmap() { | |
| 218 if (memory_ == NULL) | |
| 219 return false; | |
| 220 | |
| 221 UnmapViewOfFile(memory_); | |
| 222 memory_ = NULL; | |
| 223 return true; | |
| 224 } | |
| 225 | |
| 226 bool SharedMemory::ShareToProcessCommon(ProcessHandle process, | |
| 227 SharedMemoryHandle* new_handle, | |
| 228 bool close_self, | |
| 229 ShareMode share_mode) { | |
| 230 *new_handle = 0; | |
| 231 DWORD access = FILE_MAP_READ; | |
| 232 DWORD options = 0; | |
| 233 HANDLE mapped_file = mapped_file_; | |
| 234 HANDLE result; | |
| 235 if (share_mode == SHARE_CURRENT_MODE && !read_only_) | |
| 236 access |= FILE_MAP_WRITE; | |
| 237 if (close_self) { | |
| 238 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file. | |
| 239 options = DUPLICATE_CLOSE_SOURCE; | |
| 240 mapped_file_ = NULL; | |
| 241 Unmap(); | |
| 242 } | |
| 243 | |
| 244 if (process == GetCurrentProcess() && close_self) { | |
| 245 *new_handle = mapped_file; | |
| 246 return true; | |
| 247 } | |
| 248 | |
| 249 if (!::DuplicateHandle(GetCurrentProcess(), mapped_file, process, &result, | |
| 250 access, FALSE, options)) { | |
| 251 return false; | |
| 252 } | |
| 253 *new_handle = result; | |
| 254 return true; | |
| 255 } | |
| 256 | |
| 257 | |
| 258 void SharedMemory::Close() { | |
| 259 if (mapped_file_ != NULL) { | |
| 260 CloseHandle(mapped_file_); | |
| 261 mapped_file_ = NULL; | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 SharedMemoryHandle SharedMemory::handle() const { | |
| 266 return mapped_file_; | |
| 267 } | |
| 268 | |
| 269 } // namespace base | |
| OLD | NEW |