-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PartitionAlloc: Add MTECheckedPtr buildflag
This change adds a buildflag gating the use of `MTECheckedPtr<T>` and restores the original implementation of the tags and tag bitmaps. Bug: 1298696 Change-Id: Ied78574e9d22f0e55e94d2a48376deda118c67ae Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3495724 Reviewed-by: Bartek Nowierski <bartekn@chromium.org> Commit-Queue: Kalvin Lee <kdlee@chromium.org> Cr-Commit-Position: refs/heads/main@{#983525}
- Loading branch information
Kalvin Lee
authored and
Chromium LUCI CQ
committed
Mar 21, 2022
1 parent
445ab61
commit 240f4d1
Showing
6 changed files
with
293 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// Copyright (c) 2020 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_H_ | ||
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_H_ | ||
|
||
// This file defines types and functions for `MTECheckedPtr<T>` (cf. | ||
// `tagging.h`, which deals with real ARM MTE). | ||
|
||
#include <string.h> | ||
|
||
#include "base/allocator/buildflags.h" | ||
#include "base/allocator/partition_allocator/partition_alloc_constants.h" | ||
#include "base/allocator/partition_allocator/partition_alloc_notreached.h" | ||
#include "base/allocator/partition_allocator/partition_cookie.h" | ||
#include "base/allocator/partition_allocator/partition_tag_bitmap.h" | ||
#include "base/base_export.h" | ||
#include "build/build_config.h" | ||
|
||
namespace partition_alloc::internal { | ||
|
||
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) | ||
|
||
// Use 8 bits for the partition tag. | ||
// TODO(tasak): add a description about the partition tag. | ||
using PartitionTag = uint8_t; | ||
|
||
static_assert( | ||
sizeof(PartitionTag) == tag_bitmap::kPartitionTagSize, | ||
"sizeof(PartitionTag) must be equal to bitmap::kPartitionTagSize."); | ||
|
||
static constexpr size_t kInSlotTagBufferSize = 0; | ||
|
||
ALWAYS_INLINE PartitionTag* PartitionTagPointer(void* ptr) { | ||
// See the comment explaining the layout in partition_tag_bitmap.h. | ||
uintptr_t pointer_as_uintptr = reinterpret_cast<uintptr_t>(ptr); | ||
uintptr_t bitmap_base = | ||
(pointer_as_uintptr & kSuperPageBaseMask) + PartitionPageSize(); | ||
uintptr_t offset = | ||
(pointer_as_uintptr & kSuperPageOffsetMask) - PartitionPageSize(); | ||
// Not to depend on partition_address_space.h and PartitionAllocGigaCage | ||
// feature, use "offset" to see whether the given ptr is_direct_mapped or not. | ||
// DirectMap object should cause this PA_DCHECK's failure, as tags aren't | ||
// currently supported there. | ||
PA_DCHECK(offset >= ReservedTagBitmapSize()); | ||
size_t bitmap_offset = (offset - ReservedTagBitmapSize()) >> | ||
tag_bitmap::kBytesPerPartitionTagShift | ||
<< tag_bitmap::kPartitionTagSizeShift; | ||
return reinterpret_cast<PartitionTag* const>(bitmap_base + bitmap_offset); | ||
} | ||
|
||
ALWAYS_INLINE void PartitionTagSetValue(void* ptr, | ||
size_t size, | ||
PartitionTag value) { | ||
PA_DCHECK((size % tag_bitmap::kBytesPerPartitionTag) == 0); | ||
size_t tag_count = size >> tag_bitmap::kBytesPerPartitionTagShift; | ||
PartitionTag* tag_ptr = PartitionTagPointer(ptr); | ||
if (sizeof(PartitionTag) == 1) { | ||
memset(tag_ptr, value, tag_count); | ||
} else { | ||
while (tag_count-- > 0) | ||
*tag_ptr++ = value; | ||
} | ||
} | ||
|
||
ALWAYS_INLINE PartitionTag PartitionTagGetValue(void* ptr) { | ||
return *PartitionTagPointer(ptr); | ||
} | ||
|
||
ALWAYS_INLINE void PartitionTagClearValue(void* ptr, size_t size) { | ||
size_t tag_region_size = size >> tag_bitmap::kBytesPerPartitionTagShift | ||
<< tag_bitmap::kPartitionTagSizeShift; | ||
PA_DCHECK(!memchr(PartitionTagPointer(ptr), 0, tag_region_size)); | ||
memset(PartitionTagPointer(ptr), 0, tag_region_size); | ||
} | ||
|
||
ALWAYS_INLINE void PartitionTagIncrementValue(void* ptr, size_t size) { | ||
PartitionTag tag = PartitionTagGetValue(ptr); | ||
PartitionTag new_tag = tag; | ||
++new_tag; | ||
new_tag += !new_tag; // Avoid 0. | ||
#if DCHECK_IS_ON() | ||
// This verifies that tags for the entire slot have the same value and that | ||
// |size| doesn't exceed the slot size. | ||
size_t tag_count = size >> tag_bitmap::kBytesPerPartitionTagShift; | ||
PartitionTag* tag_ptr = PartitionTagPointer(ptr); | ||
while (tag_count-- > 0) { | ||
PA_DCHECK(tag == *tag_ptr); | ||
tag_ptr++; | ||
} | ||
#endif | ||
PartitionTagSetValue(ptr, size, new_tag); | ||
} | ||
|
||
#else // No-op versions | ||
|
||
using PartitionTag = uint8_t; | ||
|
||
static constexpr size_t kInSlotTagBufferSize = 0; | ||
|
||
ALWAYS_INLINE PartitionTag* PartitionTagPointer(void* ptr) { | ||
PA_NOTREACHED(); | ||
return nullptr; | ||
} | ||
|
||
ALWAYS_INLINE void PartitionTagSetValue(void*, size_t, PartitionTag) {} | ||
|
||
ALWAYS_INLINE PartitionTag PartitionTagGetValue(void*) { | ||
return 0; | ||
} | ||
|
||
ALWAYS_INLINE void PartitionTagClearValue(void* ptr, size_t) {} | ||
|
||
ALWAYS_INLINE void PartitionTagIncrementValue(void* ptr, size_t size) {} | ||
|
||
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) | ||
|
||
constexpr size_t kPartitionTagSizeAdjustment = kInSlotTagBufferSize; | ||
constexpr size_t kPartitionTagOffsetAdjustment = kInSlotTagBufferSize; | ||
|
||
} // namespace partition_alloc::internal | ||
|
||
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_H_ |
145 changes: 145 additions & 0 deletions
145
base/allocator/partition_allocator/partition_tag_bitmap.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
// Copyright (c) 2020 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_BITMAP_H_ | ||
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_BITMAP_H_ | ||
|
||
#include "base/allocator/buildflags.h" | ||
#include "base/allocator/partition_allocator/page_allocator_constants.h" | ||
#include "base/allocator/partition_allocator/partition_alloc_constants.h" | ||
|
||
namespace partition_alloc::internal { | ||
|
||
#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) | ||
|
||
namespace tag_bitmap { | ||
// kPartitionTagSize should be equal to sizeof(PartitionTag). | ||
// PartitionTag is defined in partition_tag.h and static_assert there | ||
// checks the condition. | ||
static constexpr size_t kPartitionTagSizeShift = 0; | ||
static constexpr size_t kPartitionTagSize = 1U << kPartitionTagSizeShift; | ||
|
||
static constexpr size_t kBytesPerPartitionTagShift = 4; | ||
// One partition tag is assigned per |kBytesPerPartitionTag| bytes in the slot | ||
// spans. | ||
// +-----------+ 0 | ||
// | | ====> 1 partition tag | ||
// +-----------+ kBytesPerPartitionTag | ||
// | | ====> 1 partition tag | ||
// +-----------+ 2*kBytesPerPartitionTag | ||
// ... | ||
// +-----------+ slot_size | ||
static constexpr size_t kBytesPerPartitionTag = 1U | ||
<< kBytesPerPartitionTagShift; | ||
static_assert( | ||
kMinBucketedOrder >= kBytesPerPartitionTagShift + 1, | ||
"MTECheckedPtr requires kBytesPerPartitionTagShift-bytes alignment."); | ||
|
||
static constexpr size_t kBytesPerPartitionTagRatio = | ||
kBytesPerPartitionTag / kPartitionTagSize; | ||
|
||
static_assert(kBytesPerPartitionTag > 0, | ||
"kBytesPerPartitionTag should be larger than 0"); | ||
static_assert( | ||
kBytesPerPartitionTag % kPartitionTagSize == 0, | ||
"kBytesPerPartitionTag should be multiples of sizeof(PartitionTag)."); | ||
|
||
constexpr size_t CeilCountOfUnits(size_t size, size_t unit_size) { | ||
return (size + unit_size - 1) / unit_size; | ||
} | ||
|
||
} // namespace tag_bitmap | ||
|
||
// kTagBitmapSize is calculated in the following way: | ||
// (1) kSuperPageSize - 2 * PartitionPageSize() = kTagBitmapSize + | ||
// SlotSpanSize() | ||
// (2) kTagBitmapSize >= SlotSpanSize() / kBytesPerPartitionTag * | ||
// sizeof(PartitionTag) | ||
//-- | ||
// (1)' SlotSpanSize() = kSuperPageSize - 2 * PartitionPageSize() - | ||
// kTagBitmapSize | ||
// (2)' SlotSpanSize() <= kTagBitmapSize * Y | ||
// (3)' Y = kBytesPerPartitionTag / sizeof(PartitionTag) = | ||
// kBytesPerPartitionTagRatio | ||
// | ||
// kTagBitmapSize * Y >= kSuperPageSize - 2 * PartitionPageSize() - | ||
// kTagBitmapSize (1 + Y) * kTagBimapSize >= kSuperPageSize - 2 * | ||
// PartitionPageSize() | ||
// Finally, | ||
// kTagBitmapSize >= (kSuperPageSize - 2 * PartitionPageSize()) / (1 + Y) | ||
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t | ||
NumPartitionPagesPerTagBitmap() { | ||
return tag_bitmap::CeilCountOfUnits( | ||
kSuperPageSize / PartitionPageSize() - 2, | ||
tag_bitmap::kBytesPerPartitionTagRatio + 1); | ||
} | ||
|
||
// To make guard pages between the tag bitmap and the slot span, calculate the | ||
// number of SystemPages of TagBitmap. If kNumSystemPagesPerTagBitmap * | ||
// SystemPageSize() < kTagBitmapSize, guard pages will be created. (c.f. no | ||
// guard pages if sizeof(PartitionTag) == 2.) | ||
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t | ||
NumSystemPagesPerTagBitmap() { | ||
return tag_bitmap::CeilCountOfUnits( | ||
kSuperPageSize / SystemPageSize() - | ||
2 * PartitionPageSize() / SystemPageSize(), | ||
tag_bitmap::kBytesPerPartitionTagRatio + 1); | ||
} | ||
|
||
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t | ||
ActualTagBitmapSize() { | ||
return NumSystemPagesPerTagBitmap() * SystemPageSize(); | ||
} | ||
|
||
// PartitionPageSize-aligned tag bitmap size. | ||
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t | ||
ReservedTagBitmapSize() { | ||
return PartitionPageSize() * NumPartitionPagesPerTagBitmap(); | ||
} | ||
|
||
#if PAGE_ALLOCATOR_CONSTANTS_ARE_CONSTEXPR | ||
static_assert(ActualTagBitmapSize() <= ReservedTagBitmapSize(), | ||
"kActualTagBitmapSize should be smaller than or equal to " | ||
"kReservedTagBitmapSize."); | ||
static_assert(ReservedTagBitmapSize() - ActualTagBitmapSize() < | ||
PartitionPageSize(), | ||
"Unused space in the tag bitmap should be smaller than " | ||
"PartitionPageSize()"); | ||
|
||
// The region available for slot spans is the reminder of the super page, after | ||
// taking away the first and last partition page (for metadata and guard pages) | ||
// and partition pages reserved for the tag bitmap. | ||
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR ALWAYS_INLINE size_t | ||
SlotSpansSize() { | ||
return kSuperPageSize - 2 * PartitionPageSize() - ReservedTagBitmapSize(); | ||
} | ||
|
||
static_assert(ActualTagBitmapSize() * tag_bitmap::kBytesPerPartitionTagRatio >= | ||
SlotSpansSize(), | ||
"bitmap is large enough to cover slot spans"); | ||
static_assert((ActualTagBitmapSize() - PartitionPageSize()) * | ||
tag_bitmap::kBytesPerPartitionTagRatio < | ||
SlotSpansSize(), | ||
"any smaller bitmap wouldn't suffice to cover slots spans"); | ||
#endif // PAGE_ALLOCATOR_CONSTANTS_ARE_CONSTEXPR | ||
|
||
#else | ||
|
||
constexpr ALWAYS_INLINE size_t NumPartitionPagesPerTagBitmap() { | ||
return 0; | ||
} | ||
|
||
constexpr ALWAYS_INLINE size_t ActualTagBitmapSize() { | ||
return 0; | ||
} | ||
|
||
constexpr ALWAYS_INLINE size_t ReservedTagBitmapSize() { | ||
return 0; | ||
} | ||
|
||
#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) | ||
|
||
} // namespace partition_alloc::internal | ||
|
||
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_TAG_BITMAP_H_ |