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