[email protected] | b05df6b | 2011-12-01 23:19:31 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 4 | |
[email protected] | 99873aa | 2013-03-29 17:46:23 | [diff] [blame] | 5 | #include "base/memory/shared_memory.h" |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 6 | |
[email protected] | 6d6797eb | 2014-08-07 22:07:43 | [diff] [blame] | 7 | #include <aclapi.h> |
avi | 9beac25 | 2015-12-24 08:44:47 | [diff] [blame] | 8 | #include <stddef.h> |
| 9 | #include <stdint.h> |
[email protected] | 6d6797eb | 2014-08-07 22:07:43 | [diff] [blame] | 10 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 11 | #include "base/logging.h" |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 12 | #include "base/metrics/histogram_macros.h" |
[email protected] | dc84fcc | 2014-07-24 11:42:59 | [diff] [blame] | 13 | #include "base/rand_util.h" |
| 14 | #include "base/strings/stringprintf.h" |
[email protected] | a4ea1f1 | 2013-06-07 18:37:07 | [diff] [blame] | 15 | #include "base/strings/utf_string_conversions.h" |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 16 | |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 17 | namespace { |
| 18 | |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 19 | // Errors that can occur during Shared Memory construction. |
| 20 | // These match tools/metrics/histograms/histograms.xml. |
| 21 | // This enum is append-only. |
| 22 | enum CreateError { |
| 23 | SUCCESS = 0, |
| 24 | SIZE_ZERO = 1, |
| 25 | SIZE_TOO_LARGE = 2, |
| 26 | INITIALIZE_ACL_FAILURE = 3, |
| 27 | INITIALIZE_SECURITY_DESC_FAILURE = 4, |
| 28 | SET_SECURITY_DESC_FAILURE = 5, |
| 29 | CREATE_FILE_MAPPING_FAILURE = 6, |
| 30 | REDUCE_PERMISSIONS_FAILURE = 7, |
| 31 | ALREADY_EXISTS = 8, |
| 32 | CREATE_ERROR_LAST = ALREADY_EXISTS |
| 33 | }; |
| 34 | |
| 35 | // Emits an UMA metric. |
| 36 | void LogError(CreateError error) { |
| 37 | UMA_HISTOGRAM_ENUMERATION("SharedMemory.CreateError", error, |
| 38 | CREATE_ERROR_LAST + 1); |
| 39 | } |
| 40 | |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 41 | typedef enum _SECTION_INFORMATION_CLASS { |
| 42 | SectionBasicInformation, |
| 43 | } SECTION_INFORMATION_CLASS; |
| 44 | |
| 45 | typedef struct _SECTION_BASIC_INFORMATION { |
| 46 | PVOID BaseAddress; |
| 47 | ULONG Attributes; |
| 48 | LARGE_INTEGER Size; |
| 49 | } SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; |
| 50 | |
| 51 | typedef ULONG(__stdcall* NtQuerySectionType)( |
| 52 | HANDLE SectionHandle, |
| 53 | SECTION_INFORMATION_CLASS SectionInformationClass, |
| 54 | PVOID SectionInformation, |
| 55 | ULONG SectionInformationLength, |
| 56 | PULONG ResultLength); |
| 57 | |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 58 | // Returns the length of the memory section starting at the supplied address. |
| 59 | size_t GetMemorySectionSize(void* address) { |
| 60 | MEMORY_BASIC_INFORMATION memory_info; |
| 61 | if (!::VirtualQuery(address, &memory_info, sizeof(memory_info))) |
| 62 | return 0; |
| 63 | return memory_info.RegionSize - (static_cast<char*>(address) - |
| 64 | static_cast<char*>(memory_info.AllocationBase)); |
| 65 | } |
| 66 | |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 67 | // Checks if the section object is safe to map. At the moment this just means |
| 68 | // it's not an image section. |
| 69 | bool IsSectionSafeToMap(HANDLE handle) { |
| 70 | static NtQuerySectionType nt_query_section_func; |
| 71 | if (!nt_query_section_func) { |
| 72 | nt_query_section_func = reinterpret_cast<NtQuerySectionType>( |
| 73 | ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection")); |
| 74 | DCHECK(nt_query_section_func); |
| 75 | } |
| 76 | |
| 77 | // The handle must have SECTION_QUERY access for this to succeed. |
| 78 | SECTION_BASIC_INFORMATION basic_information = {}; |
| 79 | ULONG status = |
| 80 | nt_query_section_func(handle, SectionBasicInformation, &basic_information, |
| 81 | sizeof(basic_information), nullptr); |
| 82 | if (status) |
| 83 | return false; |
| 84 | return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE; |
| 85 | } |
| 86 | |
erikchen | 4b12c0a | 2016-02-19 03:15:43 | [diff] [blame] | 87 | // Returns a HANDLE on success and |nullptr| on failure. |
| 88 | // This function is similar to CreateFileMapping, but removes the permissions |
| 89 | // WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE. |
| 90 | // |
| 91 | // A newly created file mapping has two sets of permissions. It has access |
| 92 | // control permissions (WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE) and |
| 93 | // file permissions (FILE_MAP_READ, FILE_MAP_WRITE, etc.). ::DuplicateHandle() |
| 94 | // with the parameter DUPLICATE_SAME_ACCESS copies both sets of permissions. |
| 95 | // |
| 96 | // The Chrome sandbox prevents HANDLEs with the WRITE_DAC permission from being |
| 97 | // duplicated into unprivileged processes. But the only way to copy file |
| 98 | // permissions is with the parameter DUPLICATE_SAME_ACCESS. This means that |
| 99 | // there is no way for a privileged process to duplicate a file mapping into an |
| 100 | // unprivileged process while maintaining the previous file permissions. |
| 101 | // |
| 102 | // By removing all access control permissions of a file mapping immediately |
| 103 | // after creation, ::DuplicateHandle() effectively only copies the file |
| 104 | // permissions. |
| 105 | HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa, |
| 106 | size_t rounded_size, |
| 107 | LPCWSTR name) { |
| 108 | HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0, |
| 109 | static_cast<DWORD>(rounded_size), name); |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 110 | if (!h) { |
| 111 | LogError(CREATE_FILE_MAPPING_FAILURE); |
erikchen | 4b12c0a | 2016-02-19 03:15:43 | [diff] [blame] | 112 | return nullptr; |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 113 | } |
erikchen | 4b12c0a | 2016-02-19 03:15:43 | [diff] [blame] | 114 | |
| 115 | HANDLE h2; |
| 116 | BOOL success = ::DuplicateHandle( |
| 117 | GetCurrentProcess(), h, GetCurrentProcess(), &h2, |
| 118 | FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, FALSE, 0); |
| 119 | BOOL rv = ::CloseHandle(h); |
| 120 | DCHECK(rv); |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 121 | |
| 122 | if (!success) { |
| 123 | LogError(REDUCE_PERMISSIONS_FAILURE); |
| 124 | return nullptr; |
| 125 | } |
| 126 | |
| 127 | return h2; |
erikchen | 4b12c0a | 2016-02-19 03:15:43 | [diff] [blame] | 128 | } |
| 129 | |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 130 | } // namespace. |
| 131 | |
[email protected] | 176aa48 | 2008-11-14 03:25:15 | [diff] [blame] | 132 | namespace base { |
| 133 | |
erikchen | baac911 | 2015-10-23 20:20:34 | [diff] [blame] | 134 | SharedMemoryCreateOptions::SharedMemoryCreateOptions() |
| 135 | : name_deprecated(nullptr), |
| 136 | open_existing_deprecated(false), |
| 137 | size(0), |
| 138 | executable(false), |
| 139 | share_read_only(false) {} |
| 140 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 141 | SharedMemory::SharedMemory() |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 142 | : external_section_(false), |
sammc | 5648c85 | 2015-07-02 01:25:00 | [diff] [blame] | 143 | mapped_file_(NULL), |
| 144 | mapped_size_(0), |
[email protected] | 8cc4194 | 2010-11-05 19:16:07 | [diff] [blame] | 145 | memory_(NULL), |
| 146 | read_only_(false), |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 147 | requested_size_(0) {} |
| 148 | |
| 149 | SharedMemory::SharedMemory(const std::wstring& name) |
| 150 | : external_section_(false), |
| 151 | name_(name), |
| 152 | mapped_file_(NULL), |
| 153 | mapped_size_(0), |
| 154 | memory_(NULL), |
| 155 | read_only_(false), |
| 156 | requested_size_(0) {} |
[email protected] | 8cc4194 | 2010-11-05 19:16:07 | [diff] [blame] | 157 | |
scottmg | d19b4f7 | 2015-06-19 22:51:00 | [diff] [blame] | 158 | SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 159 | : external_section_(true), |
| 160 | mapped_file_(handle.GetHandle()), |
sammc | 5648c85 | 2015-07-02 01:25:00 | [diff] [blame] | 161 | mapped_size_(0), |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 162 | memory_(NULL), |
| 163 | read_only_(read_only), |
sammc | 5648c85 | 2015-07-02 01:25:00 | [diff] [blame] | 164 | requested_size_(0) { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 165 | DCHECK(!handle.IsValid() || handle.BelongsToCurrentProcess()); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 166 | } |
| 167 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 168 | SharedMemory::~SharedMemory() { |
jbauman | 569918b | 2014-12-10 22:07:20 | [diff] [blame] | 169 | Unmap(); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 170 | Close(); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 171 | } |
| 172 | |
[email protected] | 5fe733de | 2009-02-11 18:59:20 | [diff] [blame] | 173 | // static |
| 174 | bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 175 | return handle.IsValid(); |
[email protected] | 5fe733de | 2009-02-11 18:59:20 | [diff] [blame] | 176 | } |
| 177 | |
[email protected] | 76aac1e | 2009-03-16 16:45:36 | [diff] [blame] | 178 | // static |
| 179 | SharedMemoryHandle SharedMemory::NULLHandle() { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 180 | return SharedMemoryHandle(); |
[email protected] | 76aac1e | 2009-03-16 16:45:36 | [diff] [blame] | 181 | } |
| 182 | |
[email protected] | b0af04c | 2009-05-18 17:46:31 | [diff] [blame] | 183 | // static |
| 184 | void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 185 | handle.Close(); |
[email protected] | b0af04c | 2009-05-18 17:46:31 | [diff] [blame] | 186 | } |
| 187 | |
[email protected] | c14eda9 | 2013-05-09 23:15:40 | [diff] [blame] | 188 | // static |
| 189 | size_t SharedMemory::GetHandleLimit() { |
| 190 | // Rounded down from value reported here: |
| 191 | // http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx |
| 192 | return static_cast<size_t>(1 << 23); |
| 193 | } |
| 194 | |
erikchen | 2096f62 | 2015-06-03 00:26:59 | [diff] [blame] | 195 | // static |
| 196 | SharedMemoryHandle SharedMemory::DuplicateHandle( |
erikchen | 8539d85 | 2015-05-30 01:49:19 | [diff] [blame] | 197 | const SharedMemoryHandle& handle) { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 198 | DCHECK(handle.BelongsToCurrentProcess()); |
| 199 | HANDLE duped_handle; |
erikchen | 2096f62 | 2015-06-03 00:26:59 | [diff] [blame] | 200 | ProcessHandle process = GetCurrentProcess(); |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 201 | BOOL success = |
| 202 | ::DuplicateHandle(process, handle.GetHandle(), process, &duped_handle, 0, |
| 203 | FALSE, DUPLICATE_SAME_ACCESS); |
erikchen | ad6f6d8 | 2016-02-08 01:34:13 | [diff] [blame] | 204 | if (success) { |
| 205 | base::SharedMemoryHandle handle(duped_handle, GetCurrentProcId()); |
| 206 | handle.SetOwnershipPassesToIPC(true); |
| 207 | return handle; |
| 208 | } |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 209 | return SharedMemoryHandle(); |
erikchen | 8539d85 | 2015-05-30 01:49:19 | [diff] [blame] | 210 | } |
| 211 | |
[email protected] | 374f1a8 | 2013-01-10 02:16:24 | [diff] [blame] | 212 | bool SharedMemory::CreateAndMapAnonymous(size_t size) { |
[email protected] | 54e3dfa2 | 2010-10-27 18:16:06 | [diff] [blame] | 213 | return CreateAnonymous(size) && Map(size); |
| 214 | } |
| 215 | |
[email protected] | b05df6b | 2011-12-01 23:19:31 | [diff] [blame] | 216 | bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 217 | // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, |
| 218 | // wasting 32k per mapping on average. |
| 219 | static const size_t kSectionMask = 65536 - 1; |
[email protected] | b05df6b | 2011-12-01 23:19:31 | [diff] [blame] | 220 | DCHECK(!options.executable); |
[email protected] | 5d2b449 | 2011-03-01 02:48:05 | [diff] [blame] | 221 | DCHECK(!mapped_file_); |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 222 | if (options.size == 0) { |
| 223 | LogError(SIZE_ZERO); |
[email protected] | 54e3dfa2 | 2010-10-27 18:16:06 | [diff] [blame] | 224 | return false; |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 225 | } |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 226 | |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 227 | // Check maximum accounting for overflow. |
| 228 | if (options.size > |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 229 | static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) { |
| 230 | LogError(SIZE_TOO_LARGE); |
[email protected] | 374f1a8 | 2013-01-10 02:16:24 | [diff] [blame] | 231 | return false; |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 232 | } |
[email protected] | 374f1a8 | 2013-01-10 02:16:24 | [diff] [blame] | 233 | |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 234 | size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; |
thestig | 8badc79 | 2014-12-04 22:14:22 | [diff] [blame] | 235 | name_ = options.name_deprecated ? |
| 236 | ASCIIToUTF16(*options.name_deprecated) : L""; |
[email protected] | 6d6797eb | 2014-08-07 22:07:43 | [diff] [blame] | 237 | SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE }; |
| 238 | SECURITY_DESCRIPTOR sd; |
| 239 | ACL dacl; |
| 240 | |
erikchen | b5856b1 | 2016-05-24 17:21:59 | [diff] [blame^] | 241 | if (name_.empty()) { |
[email protected] | 6d6797eb | 2014-08-07 22:07:43 | [diff] [blame] | 242 | // Add an empty DACL to enforce anonymous read-only sections. |
| 243 | sa.lpSecurityDescriptor = &sd; |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 244 | if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) { |
| 245 | LogError(INITIALIZE_ACL_FAILURE); |
[email protected] | 6d6797eb | 2014-08-07 22:07:43 | [diff] [blame] | 246 | return false; |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 247 | } |
| 248 | if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { |
| 249 | LogError(INITIALIZE_SECURITY_DESC_FAILURE); |
[email protected] | 6d6797eb | 2014-08-07 22:07:43 | [diff] [blame] | 250 | return false; |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 251 | } |
| 252 | if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) { |
| 253 | LogError(SET_SECURITY_DESC_FAILURE); |
[email protected] | 6d6797eb | 2014-08-07 22:07:43 | [diff] [blame] | 254 | return false; |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 255 | } |
[email protected] | 6d6797eb | 2014-08-07 22:07:43 | [diff] [blame] | 256 | |
[email protected] | dc84fcc | 2014-07-24 11:42:59 | [diff] [blame] | 257 | // Windows ignores DACLs on certain unnamed objects (like shared sections). |
| 258 | // So, we generate a random name when we need to enforce read-only. |
| 259 | uint64_t rand_values[4]; |
thestig | 8badc79 | 2014-12-04 22:14:22 | [diff] [blame] | 260 | RandBytes(&rand_values, sizeof(rand_values)); |
brucedawson | 5604a11d | 2015-10-06 19:22:00 | [diff] [blame] | 261 | name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", |
thestig | 8badc79 | 2014-12-04 22:14:22 | [diff] [blame] | 262 | rand_values[0], rand_values[1], |
| 263 | rand_values[2], rand_values[3]); |
[email protected] | dc84fcc | 2014-07-24 11:42:59 | [diff] [blame] | 264 | } |
erikchen | 4b12c0a | 2016-02-19 03:15:43 | [diff] [blame] | 265 | mapped_file_ = CreateFileMappingWithReducedPermissions( |
| 266 | &sa, rounded_size, name_.empty() ? nullptr : name_.c_str()); |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 267 | if (!mapped_file_) { |
| 268 | // The error is logged within CreateFileMappingWithReducedPermissions(). |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 269 | return false; |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 270 | } |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 271 | |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 272 | requested_size_ = options.size; |
[email protected] | 54e3dfa2 | 2010-10-27 18:16:06 | [diff] [blame] | 273 | |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 274 | // Check if the shared memory pre-exists. |
[email protected] | 54e3dfa2 | 2010-10-27 18:16:06 | [diff] [blame] | 275 | if (GetLastError() == ERROR_ALREADY_EXISTS) { |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 276 | // If the file already existed, set requested_size_ to 0 to show that |
[email protected] | 54e3dfa2 | 2010-10-27 18:16:06 | [diff] [blame] | 277 | // we don't know the size. |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 278 | requested_size_ = 0; |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 279 | external_section_ = true; |
[email protected] | ff672b7 | 2014-03-05 21:13:52 | [diff] [blame] | 280 | if (!options.open_existing_deprecated) { |
[email protected] | 54e3dfa2 | 2010-10-27 18:16:06 | [diff] [blame] | 281 | Close(); |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 282 | LogError(ALREADY_EXISTS); |
[email protected] | 54e3dfa2 | 2010-10-27 18:16:06 | [diff] [blame] | 283 | return false; |
| 284 | } |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 285 | } |
[email protected] | 54e3dfa2 | 2010-10-27 18:16:06 | [diff] [blame] | 286 | |
erikchen | 1d7cb7e | 2016-05-20 23:34:04 | [diff] [blame] | 287 | LogError(SUCCESS); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 288 | return true; |
| 289 | } |
| 290 | |
[email protected] | b6413b49b | 2010-09-29 20:32:22 | [diff] [blame] | 291 | bool SharedMemory::Delete(const std::string& name) { |
[email protected] | 9e51af9 | 2009-02-04 00:58:39 | [diff] [blame] | 292 | // intentionally empty -- there is nothing for us to do on Windows. |
| 293 | return true; |
| 294 | } |
| 295 | |
[email protected] | b6413b49b | 2010-09-29 20:32:22 | [diff] [blame] | 296 | bool SharedMemory::Open(const std::string& name, bool read_only) { |
[email protected] | 5d2b449 | 2011-03-01 02:48:05 | [diff] [blame] | 297 | DCHECK(!mapped_file_); |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 298 | DWORD access = FILE_MAP_READ | SECTION_QUERY; |
| 299 | if (!read_only) |
| 300 | access |= FILE_MAP_WRITE; |
thestig | 8badc79 | 2014-12-04 22:14:22 | [diff] [blame] | 301 | name_ = ASCIIToUTF16(name); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 302 | read_only_ = read_only; |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 303 | mapped_file_ = |
| 304 | OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str()); |
| 305 | if (!mapped_file_) |
| 306 | return false; |
| 307 | // If a name specified assume it's an external section. |
| 308 | if (!name_.empty()) |
| 309 | external_section_ = true; |
| 310 | // Note: size_ is not set in this case. |
| 311 | return true; |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 312 | } |
| 313 | |
[email protected] | e29e3f55 | 2013-01-16 09:02:34 | [diff] [blame] | 314 | bool SharedMemory::MapAt(off_t offset, size_t bytes) { |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 315 | if (mapped_file_ == NULL) |
| 316 | return false; |
| 317 | |
[email protected] | 374f1a8 | 2013-01-10 02:16:24 | [diff] [blame] | 318 | if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) |
| 319 | return false; |
| 320 | |
[email protected] | 421c150 | 2014-03-18 22:33:28 | [diff] [blame] | 321 | if (memory_) |
| 322 | return false; |
| 323 | |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 324 | if (external_section_ && !IsSectionSafeToMap(mapped_file_)) |
| 325 | return false; |
| 326 | |
avi | 9beac25 | 2015-12-24 08:44:47 | [diff] [blame] | 327 | memory_ = MapViewOfFile( |
| 328 | mapped_file_, read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, |
| 329 | static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), bytes); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 330 | if (memory_ != NULL) { |
[email protected] | 404a058 | 2012-08-18 02:17:26 | [diff] [blame] | 331 | DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & |
| 332 | (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); |
[email protected] | 67ea507 | 2013-03-28 02:02:18 | [diff] [blame] | 333 | mapped_size_ = GetMemorySectionSize(memory_); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 334 | return true; |
| 335 | } |
| 336 | return false; |
| 337 | } |
| 338 | |
| 339 | bool SharedMemory::Unmap() { |
| 340 | if (memory_ == NULL) |
| 341 | return false; |
| 342 | |
| 343 | UnmapViewOfFile(memory_); |
| 344 | memory_ = NULL; |
| 345 | return true; |
| 346 | } |
| 347 | |
| 348 | bool SharedMemory::ShareToProcessCommon(ProcessHandle process, |
thestig | 8badc79 | 2014-12-04 22:14:22 | [diff] [blame] | 349 | SharedMemoryHandle* new_handle, |
[email protected] | 5f58adab | 2013-11-20 23:41:25 | [diff] [blame] | 350 | bool close_self, |
| 351 | ShareMode share_mode) { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 352 | *new_handle = SharedMemoryHandle(); |
forshaw | 0474abe | 2015-12-18 02:16:59 | [diff] [blame] | 353 | DWORD access = FILE_MAP_READ | SECTION_QUERY; |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 354 | DWORD options = 0; |
| 355 | HANDLE mapped_file = mapped_file_; |
| 356 | HANDLE result; |
[email protected] | 5f58adab | 2013-11-20 23:41:25 | [diff] [blame] | 357 | if (share_mode == SHARE_CURRENT_MODE && !read_only_) |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 358 | access |= FILE_MAP_WRITE; |
| 359 | if (close_self) { |
| 360 | // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file. |
| 361 | options = DUPLICATE_CLOSE_SOURCE; |
| 362 | mapped_file_ = NULL; |
| 363 | Unmap(); |
| 364 | } |
| 365 | |
| 366 | if (process == GetCurrentProcess() && close_self) { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 367 | *new_handle = SharedMemoryHandle(mapped_file, base::GetCurrentProcId()); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 368 | return true; |
| 369 | } |
| 370 | |
erikchen | 2096f62 | 2015-06-03 00:26:59 | [diff] [blame] | 371 | if (!::DuplicateHandle(GetCurrentProcess(), mapped_file, process, &result, |
| 372 | access, FALSE, options)) { |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 373 | return false; |
erikchen | 2096f62 | 2015-06-03 00:26:59 | [diff] [blame] | 374 | } |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 375 | *new_handle = SharedMemoryHandle(result, base::GetProcId(process)); |
erikchen | 71bc3b2 | 2016-02-01 22:14:28 | [diff] [blame] | 376 | new_handle->SetOwnershipPassesToIPC(true); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 377 | return true; |
| 378 | } |
| 379 | |
| 380 | |
| 381 | void SharedMemory::Close() { |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 382 | if (mapped_file_ != NULL) { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 383 | ::CloseHandle(mapped_file_); |
initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 384 | mapped_file_ = NULL; |
| 385 | } |
| 386 | } |
| 387 | |
[email protected] | 5fe733de | 2009-02-11 18:59:20 | [diff] [blame] | 388 | SharedMemoryHandle SharedMemory::handle() const { |
erikchen | 5ea2ab7 | 2015-09-25 22:34:31 | [diff] [blame] | 389 | return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId()); |
[email protected] | 5fe733de | 2009-02-11 18:59:20 | [diff] [blame] | 390 | } |
| 391 | |
[email protected] | 176aa48 | 2008-11-14 03:25:15 | [diff] [blame] | 392 | } // namespace base |