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