| 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 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 | 133 |
| 134 SharedMemoryCreateOptions::SharedMemoryCreateOptions() | 134 SharedMemoryCreateOptions::SharedMemoryCreateOptions() |
| 135 : name_deprecated(nullptr), | 135 : name_deprecated(nullptr), |
| 136 open_existing_deprecated(false), | 136 open_existing_deprecated(false), |
| 137 size(0), | 137 size(0), |
| 138 executable(false), | 138 executable(false), |
| 139 share_read_only(false) {} | 139 share_read_only(false) {} |
| 140 | 140 |
| 141 SharedMemory::SharedMemory() | 141 SharedMemory::SharedMemory() |
| 142 : external_section_(false), | 142 : external_section_(false), |
| 143 mapped_file_(NULL), | |
| 144 mapped_size_(0), | 143 mapped_size_(0), |
| 145 memory_(NULL), | 144 memory_(NULL), |
| 146 read_only_(false), | 145 read_only_(false), |
| 147 requested_size_(0) {} | 146 requested_size_(0) {} |
| 148 | 147 |
| 149 SharedMemory::SharedMemory(const std::wstring& name) | 148 SharedMemory::SharedMemory(const std::wstring& name) |
| 150 : external_section_(false), | 149 : external_section_(false), |
| 151 name_(name), | 150 name_(name), |
| 152 mapped_file_(NULL), | |
| 153 mapped_size_(0), | 151 mapped_size_(0), |
| 154 memory_(NULL), | 152 memory_(NULL), |
| 155 read_only_(false), | 153 read_only_(false), |
| 156 requested_size_(0) {} | 154 requested_size_(0) {} |
| 157 | 155 |
| 158 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) | 156 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) |
| 159 : external_section_(true), | 157 : external_section_(true), |
| 160 mapped_file_(handle.GetHandle()), | |
| 161 mapped_size_(0), | 158 mapped_size_(0), |
| 162 memory_(NULL), | 159 memory_(NULL), |
| 163 read_only_(read_only), | 160 read_only_(read_only), |
| 164 requested_size_(0) { | 161 requested_size_(0) { |
| 165 DCHECK(!handle.IsValid() || handle.BelongsToCurrentProcess()); | 162 DCHECK(!handle.IsValid() || handle.BelongsToCurrentProcess()); |
| 163 mapped_file_.Set(handle.GetHandle()); |
| 166 } | 164 } |
| 167 | 165 |
| 168 SharedMemory::~SharedMemory() { | 166 SharedMemory::~SharedMemory() { |
| 169 Unmap(); | 167 Unmap(); |
| 170 Close(); | 168 Close(); |
| 171 } | 169 } |
| 172 | 170 |
| 173 // static | 171 // static |
| 174 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { | 172 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { |
| 175 return handle.IsValid(); | 173 return handle.IsValid(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 | 209 |
| 212 bool SharedMemory::CreateAndMapAnonymous(size_t size) { | 210 bool SharedMemory::CreateAndMapAnonymous(size_t size) { |
| 213 return CreateAnonymous(size) && Map(size); | 211 return CreateAnonymous(size) && Map(size); |
| 214 } | 212 } |
| 215 | 213 |
| 216 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { | 214 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { |
| 217 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, | 215 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, |
| 218 // wasting 32k per mapping on average. | 216 // wasting 32k per mapping on average. |
| 219 static const size_t kSectionMask = 65536 - 1; | 217 static const size_t kSectionMask = 65536 - 1; |
| 220 DCHECK(!options.executable); | 218 DCHECK(!options.executable); |
| 221 DCHECK(!mapped_file_); | 219 DCHECK(!mapped_file_.Get()); |
| 222 if (options.size == 0) { | 220 if (options.size == 0) { |
| 223 LogError(SIZE_ZERO); | 221 LogError(SIZE_ZERO); |
| 224 return false; | 222 return false; |
| 225 } | 223 } |
| 226 | 224 |
| 227 // Check maximum accounting for overflow. | 225 // Check maximum accounting for overflow. |
| 228 if (options.size > | 226 if (options.size > |
| 229 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) { | 227 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) { |
| 230 LogError(SIZE_TOO_LARGE); | 228 LogError(SIZE_TOO_LARGE); |
| 231 return false; | 229 return false; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 255 } | 253 } |
| 256 | 254 |
| 257 // Windows ignores DACLs on certain unnamed objects (like shared sections). | 255 // Windows ignores DACLs on certain unnamed objects (like shared sections). |
| 258 // So, we generate a random name when we need to enforce read-only. | 256 // So, we generate a random name when we need to enforce read-only. |
| 259 uint64_t rand_values[4]; | 257 uint64_t rand_values[4]; |
| 260 RandBytes(&rand_values, sizeof(rand_values)); | 258 RandBytes(&rand_values, sizeof(rand_values)); |
| 261 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", | 259 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", |
| 262 rand_values[0], rand_values[1], | 260 rand_values[0], rand_values[1], |
| 263 rand_values[2], rand_values[3]); | 261 rand_values[2], rand_values[3]); |
| 264 } | 262 } |
| 265 mapped_file_ = CreateFileMappingWithReducedPermissions( | 263 mapped_file_.Set(CreateFileMappingWithReducedPermissions( |
| 266 &sa, rounded_size, name_.empty() ? nullptr : name_.c_str()); | 264 &sa, rounded_size, name_.empty() ? nullptr : name_.c_str())); |
| 267 if (!mapped_file_) { | 265 if (!mapped_file_.IsValid()) { |
| 268 // The error is logged within CreateFileMappingWithReducedPermissions(). | 266 // The error is logged within CreateFileMappingWithReducedPermissions(). |
| 269 return false; | 267 return false; |
| 270 } | 268 } |
| 271 | 269 |
| 272 requested_size_ = options.size; | 270 requested_size_ = options.size; |
| 273 | 271 |
| 274 // Check if the shared memory pre-exists. | 272 // Check if the shared memory pre-exists. |
| 275 if (GetLastError() == ERROR_ALREADY_EXISTS) { | 273 if (GetLastError() == ERROR_ALREADY_EXISTS) { |
| 276 // If the file already existed, set requested_size_ to 0 to show that | 274 // If the file already existed, set requested_size_ to 0 to show that |
| 277 // we don't know the size. | 275 // we don't know the size. |
| 278 requested_size_ = 0; | 276 requested_size_ = 0; |
| 279 external_section_ = true; | 277 external_section_ = true; |
| 280 if (!options.open_existing_deprecated) { | 278 if (!options.open_existing_deprecated) { |
| 281 Close(); | 279 Close(); |
| 282 LogError(ALREADY_EXISTS); | 280 LogError(ALREADY_EXISTS); |
| 283 return false; | 281 return false; |
| 284 } | 282 } |
| 285 } | 283 } |
| 286 | 284 |
| 287 LogError(SUCCESS); | 285 LogError(SUCCESS); |
| 288 return true; | 286 return true; |
| 289 } | 287 } |
| 290 | 288 |
| 291 bool SharedMemory::Delete(const std::string& name) { | 289 bool SharedMemory::Delete(const std::string& name) { |
| 292 // intentionally empty -- there is nothing for us to do on Windows. | 290 // intentionally empty -- there is nothing for us to do on Windows. |
| 293 return true; | 291 return true; |
| 294 } | 292 } |
| 295 | 293 |
| 296 bool SharedMemory::Open(const std::string& name, bool read_only) { | 294 bool SharedMemory::Open(const std::string& name, bool read_only) { |
| 297 DCHECK(!mapped_file_); | 295 DCHECK(!mapped_file_.Get()); |
| 298 DWORD access = FILE_MAP_READ | SECTION_QUERY; | 296 DWORD access = FILE_MAP_READ | SECTION_QUERY; |
| 299 if (!read_only) | 297 if (!read_only) |
| 300 access |= FILE_MAP_WRITE; | 298 access |= FILE_MAP_WRITE; |
| 301 name_ = ASCIIToUTF16(name); | 299 name_ = ASCIIToUTF16(name); |
| 302 read_only_ = read_only; | 300 read_only_ = read_only; |
| 303 mapped_file_ = | 301 mapped_file_.Set( |
| 304 OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str()); | 302 OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str())); |
| 305 if (!mapped_file_) | 303 if (!mapped_file_.IsValid()) |
| 306 return false; | 304 return false; |
| 307 // If a name specified assume it's an external section. | 305 // If a name specified assume it's an external section. |
| 308 if (!name_.empty()) | 306 if (!name_.empty()) |
| 309 external_section_ = true; | 307 external_section_ = true; |
| 310 // Note: size_ is not set in this case. | 308 // Note: size_ is not set in this case. |
| 311 return true; | 309 return true; |
| 312 } | 310 } |
| 313 | 311 |
| 314 bool SharedMemory::MapAt(off_t offset, size_t bytes) { | 312 bool SharedMemory::MapAt(off_t offset, size_t bytes) { |
| 315 if (mapped_file_ == NULL) | 313 if (!mapped_file_.Get()) |
| 316 return false; | 314 return false; |
| 317 | 315 |
| 318 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) | 316 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) |
| 319 return false; | 317 return false; |
| 320 | 318 |
| 321 if (memory_) | 319 if (memory_) |
| 322 return false; | 320 return false; |
| 323 | 321 |
| 324 if (external_section_ && !IsSectionSafeToMap(mapped_file_)) | 322 if (external_section_ && !IsSectionSafeToMap(mapped_file_.Get())) |
| 325 return false; | 323 return false; |
| 326 | 324 |
| 327 memory_ = MapViewOfFile( | 325 memory_ = MapViewOfFile( |
| 328 mapped_file_, read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, | 326 mapped_file_.Get(), |
| 327 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, |
| 329 static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), bytes); | 328 static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), bytes); |
| 330 if (memory_ != NULL) { | 329 if (memory_ != NULL) { |
| 331 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & | 330 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & |
| 332 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); | 331 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); |
| 333 mapped_size_ = GetMemorySectionSize(memory_); | 332 mapped_size_ = GetMemorySectionSize(memory_); |
| 334 return true; | 333 return true; |
| 335 } | 334 } |
| 336 return false; | 335 return false; |
| 337 } | 336 } |
| 338 | 337 |
| 339 bool SharedMemory::Unmap() { | 338 bool SharedMemory::Unmap() { |
| 340 if (memory_ == NULL) | 339 if (memory_ == NULL) |
| 341 return false; | 340 return false; |
| 342 | 341 |
| 343 UnmapViewOfFile(memory_); | 342 UnmapViewOfFile(memory_); |
| 344 memory_ = NULL; | 343 memory_ = NULL; |
| 345 return true; | 344 return true; |
| 346 } | 345 } |
| 347 | 346 |
| 348 bool SharedMemory::ShareToProcessCommon(ProcessHandle process, | 347 bool SharedMemory::ShareToProcessCommon(ProcessHandle process, |
| 349 SharedMemoryHandle* new_handle, | 348 SharedMemoryHandle* new_handle, |
| 350 bool close_self, | 349 bool close_self, |
| 351 ShareMode share_mode) { | 350 ShareMode share_mode) { |
| 352 *new_handle = SharedMemoryHandle(); | 351 *new_handle = SharedMemoryHandle(); |
| 353 DWORD access = FILE_MAP_READ | SECTION_QUERY; | 352 DWORD access = FILE_MAP_READ | SECTION_QUERY; |
| 354 DWORD options = 0; | 353 DWORD options = 0; |
| 355 HANDLE mapped_file = mapped_file_; | 354 HANDLE mapped_file = mapped_file_.Get(); |
| 356 HANDLE result; | 355 HANDLE result; |
| 357 if (share_mode == SHARE_CURRENT_MODE && !read_only_) | 356 if (share_mode == SHARE_CURRENT_MODE && !read_only_) |
| 358 access |= FILE_MAP_WRITE; | 357 access |= FILE_MAP_WRITE; |
| 359 if (close_self) { | 358 if (close_self) { |
| 360 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file. | 359 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file. |
| 361 options = DUPLICATE_CLOSE_SOURCE; | 360 options = DUPLICATE_CLOSE_SOURCE; |
| 362 mapped_file_ = NULL; | 361 HANDLE detached_handle = mapped_file_.Take(); |
| 362 DCHECK_EQ(detached_handle, mapped_file); |
| 363 Unmap(); | 363 Unmap(); |
| 364 } | 364 } |
| 365 | 365 |
| 366 if (process == GetCurrentProcess() && close_self) { | 366 if (process == GetCurrentProcess() && close_self) { |
| 367 *new_handle = SharedMemoryHandle(mapped_file, base::GetCurrentProcId()); | 367 *new_handle = SharedMemoryHandle(mapped_file, base::GetCurrentProcId()); |
| 368 return true; | 368 return true; |
| 369 } | 369 } |
| 370 | 370 |
| 371 if (!::DuplicateHandle(GetCurrentProcess(), mapped_file, process, &result, | 371 if (!::DuplicateHandle(GetCurrentProcess(), mapped_file, process, &result, |
| 372 access, FALSE, options)) { | 372 access, FALSE, options)) { |
| 373 return false; | 373 return false; |
| 374 } | 374 } |
| 375 *new_handle = SharedMemoryHandle(result, base::GetProcId(process)); | 375 *new_handle = SharedMemoryHandle(result, base::GetProcId(process)); |
| 376 new_handle->SetOwnershipPassesToIPC(true); | 376 new_handle->SetOwnershipPassesToIPC(true); |
| 377 return true; | 377 return true; |
| 378 } | 378 } |
| 379 | 379 |
| 380 | 380 |
| 381 void SharedMemory::Close() { | 381 void SharedMemory::Close() { |
| 382 if (mapped_file_ != NULL) { | 382 mapped_file_.Close(); |
| 383 ::CloseHandle(mapped_file_); | |
| 384 mapped_file_ = NULL; | |
| 385 } | |
| 386 } | 383 } |
| 387 | 384 |
| 388 SharedMemoryHandle SharedMemory::handle() const { | 385 SharedMemoryHandle SharedMemory::handle() const { |
| 389 return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId()); | 386 return SharedMemoryHandle(mapped_file_.Get(), base::GetCurrentProcId()); |
| 390 } | 387 } |
| 391 | 388 |
| 392 } // namespace base | 389 } // namespace base |
| OLD | NEW |