| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/shared_memory.h" | 5 #include "base/memory/shared_memory.h" |
| 6 | 6 |
| 7 #include <aclapi.h> | 7 #include <aclapi.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/unguessable_token.h" |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| 19 // Errors that can occur during Shared Memory construction. | 20 // Errors that can occur during Shared Memory construction. |
| 20 // These match tools/metrics/histograms/histograms.xml. | 21 // These match tools/metrics/histograms/histograms.xml. |
| 21 // This enum is append-only. | 22 // This enum is append-only. |
| 22 enum CreateError { | 23 enum CreateError { |
| 23 SUCCESS = 0, | 24 SUCCESS = 0, |
| 24 SIZE_ZERO = 1, | 25 SIZE_ZERO = 1, |
| 25 SIZE_TOO_LARGE = 2, | 26 SIZE_TOO_LARGE = 2, |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 | 234 |
| 234 // Windows ignores DACLs on certain unnamed objects (like shared sections). | 235 // Windows ignores DACLs on certain unnamed objects (like shared sections). |
| 235 // So, we generate a random name when we need to enforce read-only. | 236 // So, we generate a random name when we need to enforce read-only. |
| 236 uint64_t rand_values[4]; | 237 uint64_t rand_values[4]; |
| 237 RandBytes(&rand_values, sizeof(rand_values)); | 238 RandBytes(&rand_values, sizeof(rand_values)); |
| 238 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", | 239 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", |
| 239 rand_values[0], rand_values[1], | 240 rand_values[0], rand_values[1], |
| 240 rand_values[2], rand_values[3]); | 241 rand_values[2], rand_values[3]); |
| 241 } | 242 } |
| 242 DCHECK(!name_.empty()); | 243 DCHECK(!name_.empty()); |
| 243 shm_ = SharedMemoryHandle(CreateFileMappingWithReducedPermissions( | 244 shm_ = SharedMemoryHandle( |
| 244 &sa, rounded_size, name_.c_str())); | 245 CreateFileMappingWithReducedPermissions(&sa, rounded_size, name_.c_str()), |
| 246 UnguessableToken::Create()); |
| 245 if (!shm_.IsValid()) { | 247 if (!shm_.IsValid()) { |
| 246 // The error is logged within CreateFileMappingWithReducedPermissions(). | 248 // The error is logged within CreateFileMappingWithReducedPermissions(). |
| 247 return false; | 249 return false; |
| 248 } | 250 } |
| 249 | 251 |
| 250 requested_size_ = options.size; | 252 requested_size_ = options.size; |
| 251 | 253 |
| 252 // Check if the shared memory pre-exists. | 254 // Check if the shared memory pre-exists. |
| 253 if (GetLastError() == ERROR_ALREADY_EXISTS) { | 255 if (GetLastError() == ERROR_ALREADY_EXISTS) { |
| 254 // If the file already existed, set requested_size_ to 0 to show that | 256 // If the file already existed, set requested_size_ to 0 to show that |
| (...skipping 17 matching lines...) Expand all Loading... |
| 272 return true; | 274 return true; |
| 273 } | 275 } |
| 274 | 276 |
| 275 bool SharedMemory::Open(const std::string& name, bool read_only) { | 277 bool SharedMemory::Open(const std::string& name, bool read_only) { |
| 276 DCHECK(!shm_.IsValid()); | 278 DCHECK(!shm_.IsValid()); |
| 277 DWORD access = FILE_MAP_READ | SECTION_QUERY; | 279 DWORD access = FILE_MAP_READ | SECTION_QUERY; |
| 278 if (!read_only) | 280 if (!read_only) |
| 279 access |= FILE_MAP_WRITE; | 281 access |= FILE_MAP_WRITE; |
| 280 name_ = ASCIIToUTF16(name); | 282 name_ = ASCIIToUTF16(name); |
| 281 read_only_ = read_only; | 283 read_only_ = read_only; |
| 284 |
| 285 // This form of sharing shared memory is deprecated. https://crbug.com/345734. |
| 286 // However, we can't get rid of it without a significant refactor because its |
| 287 // used to communicate between two versions of the same service process, very |
| 288 // early in the life cycle. |
| 289 // Technically, we should also pass the GUID from the original shared memory |
| 290 // region. We don't do that - this means that we will overcount this memory, |
| 291 // which thankfully isn't relevant since Chrome only communicates with a |
| 292 // single version of the service process. |
| 282 shm_ = SharedMemoryHandle( | 293 shm_ = SharedMemoryHandle( |
| 283 OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str())); | 294 OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str()), |
| 295 UnguessableToken::Create()); |
| 284 if (!shm_.IsValid()) | 296 if (!shm_.IsValid()) |
| 285 return false; | 297 return false; |
| 286 // If a name specified assume it's an external section. | 298 // If a name specified assume it's an external section. |
| 287 if (!name_.empty()) | 299 if (!name_.empty()) |
| 288 external_section_ = true; | 300 external_section_ = true; |
| 289 // Note: size_ is not set in this case. | 301 // Note: size_ is not set in this case. |
| 290 return true; | 302 return true; |
| 291 } | 303 } |
| 292 | 304 |
| 293 bool SharedMemory::MapAt(off_t offset, size_t bytes) { | 305 bool SharedMemory::MapAt(off_t offset, size_t bytes) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 return true; | 337 return true; |
| 326 } | 338 } |
| 327 | 339 |
| 328 SharedMemoryHandle SharedMemory::GetReadOnlyHandle() { | 340 SharedMemoryHandle SharedMemory::GetReadOnlyHandle() { |
| 329 HANDLE result; | 341 HANDLE result; |
| 330 ProcessHandle process = GetCurrentProcess(); | 342 ProcessHandle process = GetCurrentProcess(); |
| 331 if (!::DuplicateHandle(process, shm_.GetHandle(), process, &result, | 343 if (!::DuplicateHandle(process, shm_.GetHandle(), process, &result, |
| 332 FILE_MAP_READ | SECTION_QUERY, FALSE, 0)) { | 344 FILE_MAP_READ | SECTION_QUERY, FALSE, 0)) { |
| 333 return SharedMemoryHandle(); | 345 return SharedMemoryHandle(); |
| 334 } | 346 } |
| 335 SharedMemoryHandle handle = SharedMemoryHandle(result); | 347 SharedMemoryHandle handle = SharedMemoryHandle(result, shm_.GetGUID()); |
| 336 handle.SetOwnershipPassesToIPC(true); | 348 handle.SetOwnershipPassesToIPC(true); |
| 337 return handle; | 349 return handle; |
| 338 } | 350 } |
| 339 | 351 |
| 340 void SharedMemory::Close() { | 352 void SharedMemory::Close() { |
| 341 if (shm_.IsValid()) { | 353 if (shm_.IsValid()) { |
| 342 shm_.Close(); | 354 shm_.Close(); |
| 343 shm_ = SharedMemoryHandle(); | 355 shm_ = SharedMemoryHandle(); |
| 344 } | 356 } |
| 345 } | 357 } |
| 346 | 358 |
| 347 SharedMemoryHandle SharedMemory::handle() const { | 359 SharedMemoryHandle SharedMemory::handle() const { |
| 348 return shm_; | 360 return shm_; |
| 349 } | 361 } |
| 350 | 362 |
| 351 SharedMemoryHandle SharedMemory::TakeHandle() { | 363 SharedMemoryHandle SharedMemory::TakeHandle() { |
| 352 SharedMemoryHandle handle(shm_); | 364 SharedMemoryHandle handle(shm_); |
| 353 handle.SetOwnershipPassesToIPC(true); | 365 handle.SetOwnershipPassesToIPC(true); |
| 354 shm_ = SharedMemoryHandle(); | 366 shm_ = SharedMemoryHandle(); |
| 355 memory_ = nullptr; | 367 memory_ = nullptr; |
| 356 mapped_size_ = 0; | 368 mapped_size_ = 0; |
| 357 return handle; | 369 return handle; |
| 358 } | 370 } |
| 359 | 371 |
| 360 } // namespace base | 372 } // namespace base |
| OLD | NEW |