| OLD | NEW |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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/metrics/persistent_memory_allocator.h" | 5 #include "base/metrics/persistent_memory_allocator.h" |
| 6 | 6 |
| 7 #include <assert.h> | 7 #include <assert.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 | 9 |
| 10 #include "base/files/memory_mapped_file.h" | 10 #include "base/files/memory_mapped_file.h" |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 156 |
| 157 // These atomics operate inter-process and so must be lock-free. The local | 157 // These atomics operate inter-process and so must be lock-free. The local |
| 158 // casts are to make sure it can be evaluated at compile time to a constant. | 158 // casts are to make sure it can be evaluated at compile time to a constant. |
| 159 CHECK(((SharedMetadata*)0)->freeptr.is_lock_free()); | 159 CHECK(((SharedMetadata*)0)->freeptr.is_lock_free()); |
| 160 CHECK(((SharedMetadata*)0)->flags.is_lock_free()); | 160 CHECK(((SharedMetadata*)0)->flags.is_lock_free()); |
| 161 CHECK(((BlockHeader*)0)->next.is_lock_free()); | 161 CHECK(((BlockHeader*)0)->next.is_lock_free()); |
| 162 CHECK(corrupt_.is_lock_free()); | 162 CHECK(corrupt_.is_lock_free()); |
| 163 | 163 |
| 164 if (shared_meta()->cookie != kGlobalCookie) { | 164 if (shared_meta()->cookie != kGlobalCookie) { |
| 165 if (readonly) { | 165 if (readonly) { |
| 166 NOTREACHED(); | |
| 167 SetCorrupt(); | 166 SetCorrupt(); |
| 168 return; | 167 return; |
| 169 } | 168 } |
| 170 | 169 |
| 171 // This block is only executed when a completely new memory segment is | 170 // This block is only executed when a completely new memory segment is |
| 172 // being initialized. It's unshared and single-threaded... | 171 // being initialized. It's unshared and single-threaded... |
| 173 volatile BlockHeader* const first_block = | 172 volatile BlockHeader* const first_block = |
| 174 reinterpret_cast<volatile BlockHeader*>(mem_base_ + | 173 reinterpret_cast<volatile BlockHeader*>(mem_base_ + |
| 175 sizeof(SharedMetadata)); | 174 sizeof(SharedMetadata)); |
| 176 if (shared_meta()->cookie != 0 || | 175 if (shared_meta()->cookie != 0 || |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 | 207 |
| 209 // Allocate space for the name so other processes can learn it. | 208 // Allocate space for the name so other processes can learn it. |
| 210 if (!name.empty()) { | 209 if (!name.empty()) { |
| 211 const size_t name_length = name.length() + 1; | 210 const size_t name_length = name.length() + 1; |
| 212 shared_meta()->name = Allocate(name_length, 0); | 211 shared_meta()->name = Allocate(name_length, 0); |
| 213 char* name_cstr = GetAsObject<char>(shared_meta()->name, 0); | 212 char* name_cstr = GetAsObject<char>(shared_meta()->name, 0); |
| 214 if (name_cstr) | 213 if (name_cstr) |
| 215 strcpy(name_cstr, name.c_str()); | 214 strcpy(name_cstr, name.c_str()); |
| 216 } | 215 } |
| 217 } else { | 216 } else { |
| 218 if (readonly) { | 217 if (!readonly) { |
| 219 // For read-only access, validate reasonable ctor parameters. | |
| 220 DCHECK_GE(mem_size_, shared_meta()->freeptr.load()); | |
| 221 } else { | |
| 222 // The allocator is attaching to a previously initialized segment of | 218 // The allocator is attaching to a previously initialized segment of |
| 223 // memory. Make sure the embedded data matches what has been passed. | 219 // memory. Make sure the embedded data matches what has been passed. |
| 224 if (shared_meta()->size != mem_size_ || | 220 if (shared_meta()->size != mem_size_ || |
| 225 shared_meta()->page_size != mem_page_) { | 221 shared_meta()->page_size != mem_page_) { |
| 226 NOTREACHED(); | 222 NOTREACHED(); |
| 227 SetCorrupt(); | 223 SetCorrupt(); |
| 228 } | 224 } |
| 229 } | 225 } |
| 230 } | 226 } |
| 231 } | 227 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 return std::min(shared_meta()->freeptr.load(), mem_size_); | 271 return std::min(shared_meta()->freeptr.load(), mem_size_); |
| 276 } | 272 } |
| 277 | 273 |
| 278 size_t PersistentMemoryAllocator::GetAllocSize(Reference ref) const { | 274 size_t PersistentMemoryAllocator::GetAllocSize(Reference ref) const { |
| 279 const volatile BlockHeader* const block = GetBlock(ref, 0, 0, false, false); | 275 const volatile BlockHeader* const block = GetBlock(ref, 0, 0, false, false); |
| 280 if (!block) | 276 if (!block) |
| 281 return 0; | 277 return 0; |
| 282 uint32_t size = block->size; | 278 uint32_t size = block->size; |
| 283 // Header was verified by GetBlock() but a malicious actor could change | 279 // Header was verified by GetBlock() but a malicious actor could change |
| 284 // the value between there and here. Check it again. | 280 // the value between there and here. Check it again. |
| 285 if (size <= sizeof(BlockHeader) || ref + size >= mem_size_) { | 281 if (size <= sizeof(BlockHeader) || ref + size > mem_size_) { |
| 286 SetCorrupt(); | 282 SetCorrupt(); |
| 287 return 0; | 283 return 0; |
| 288 } | 284 } |
| 289 return size - sizeof(BlockHeader); | 285 return size - sizeof(BlockHeader); |
| 290 } | 286 } |
| 291 | 287 |
| 292 uint32_t PersistentMemoryAllocator::GetType(Reference ref) const { | 288 uint32_t PersistentMemoryAllocator::GetType(Reference ref) const { |
| 293 const volatile BlockHeader* const block = GetBlock(ref, 0, 0, false, false); | 289 const volatile BlockHeader* const block = GetBlock(ref, 0, 0, false, false); |
| 294 if (!block) | 290 if (!block) |
| 295 return 0; | 291 return 0; |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 FilePersistentMemoryAllocator::~FilePersistentMemoryAllocator() { | 665 FilePersistentMemoryAllocator::~FilePersistentMemoryAllocator() { |
| 670 } | 666 } |
| 671 | 667 |
| 672 // static | 668 // static |
| 673 bool FilePersistentMemoryAllocator::IsFileAcceptable( | 669 bool FilePersistentMemoryAllocator::IsFileAcceptable( |
| 674 const MemoryMappedFile& file) { | 670 const MemoryMappedFile& file) { |
| 675 return IsMemoryAcceptable(file.data(), file.length(), 0, true); | 671 return IsMemoryAcceptable(file.data(), file.length(), 0, true); |
| 676 } | 672 } |
| 677 | 673 |
| 678 } // namespace base | 674 } // namespace base |
| OLD | NEW |