commit b2c4ff8d5d8cdbf2487363a5b8d68b6485706069 Author: Richard Townsend Date: Thu May 18 22:51:36 2023 +0000 Reland "Reland "mte: refactor the tagging functions to use ifuncs"" This is a reland of commit 2321ea383c006149c3b496a515f54fb3aebdc34c and a revert of commit adfb1c2c6ceb3daf210cef1e5688541ebc561e20. It was reverted because of a problem with android-arm64 orderfile generation, which is now resolved. Original change's description: > Reland "mte: refactor the tagging functions to use ifuncs" > > This was reverted due to a toolchain problem affecting ThinLTO, > resolved in [1] > > [1] https://reviews.llvm.org/D144982 > > This reverts commit 6c22e41fc3ffd305359f17b2423c37c2c976acf3. > > Bug: 1137393 > Change-Id: I991e12618f98cdf8b89ec83cad06e30ad60d332e > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4473870 > Reviewed-by: Keishi Hattori > Commit-Queue: Richard Townsend > Cr-Commit-Position: refs/heads/main@{#1135862} Bug: 1137393, 1440531 Change-Id: I4cd1911a36cf55ee1c06e6ffda971866c93fa741 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4517702 Commit-Queue: Richard Townsend Reviewed-by: Keishi Hattori Cr-Commit-Position: refs/heads/main@{#1146244} diff --git a/base/allocator/partition_allocator/partition_root.cc b/base/allocator/partition_allocator/partition_root.cc index 486594e81f823..8ab37f6dec750 100644 --- a/base/allocator/partition_allocator/partition_root.cc +++ b/base/allocator/partition_allocator/partition_root.cc @@ -869,10 +869,6 @@ void PartitionRoot::Init(PartitionOptions opts) { return; } - // Swaps out the active no-op tagging intrinsics with MTE-capable ones, if - // running on the right hardware. - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); - #if BUILDFLAG(HAS_64_BIT_POINTERS) // Reserve address space for partition alloc. internal::PartitionAddressSpace::Init(); diff --git a/base/allocator/partition_allocator/tagging.cc b/base/allocator/partition_allocator/tagging.cc index a8a74155de4e1..ea7ac2af82c88 100644 --- a/base/allocator/partition_allocator/tagging.cc +++ b/base/allocator/partition_allocator/tagging.cc @@ -12,7 +12,9 @@ #if PA_CONFIG(HAS_MEMORY_TAGGING) #include +#include #include +#include #include #define PR_SET_TAGGED_ADDR_CTRL 55 #define PR_GET_TAGGED_ADDR_CTRL 56 @@ -119,12 +121,6 @@ namespace { return ret; } -#if PA_CONFIG(HAS_MEMORY_TAGGING) -static bool HasCPUMemoryTaggingExtension() { - return base::CPU::GetInstanceNoAllocation().has_mte(); -} -#endif // PA_CONFIG(HAS_MEMORY_TAGGING) - #if PA_CONFIG(HAS_MEMORY_TAGGING) void* TagRegionRandomlyForMTE(void* ptr, size_t sz, uint64_t mask) { // Randomly tag a region (MTE-enabled systems only). The first 16-byte @@ -166,7 +162,6 @@ void* RemaskVoidPtrForMTE(void* ptr) { } return nullptr; } -#endif void* TagRegionIncrementNoOp(void* ptr, size_t sz) { // Region parameters are checked even on non-MTE systems to check the @@ -183,24 +178,49 @@ void* TagRegionRandomlyNoOp(void* ptr, size_t sz, uint64_t mask) { void* RemaskVoidPtrNoOp(void* ptr) { return ptr; } +#endif } // namespace -void InitializeMTESupportIfNeeded() { #if PA_CONFIG(HAS_MEMORY_TAGGING) - if (HasCPUMemoryTaggingExtension()) { - global_remask_void_ptr_fn = RemaskVoidPtrForMTE; - global_tag_memory_range_increment_fn = TagRegionIncrementForMTE; - global_tag_memory_range_randomly_fn = TagRegionRandomlyForMTE; +using RemaskPtrInternalFn = void*(void* ptr); +using TagMemoryRangeIncrementInternalFn = void*(void* ptr, size_t size); + +using TagMemoryRangeRandomlyInternalFn = void*(void* ptr, + size_t size, + uint64_t mask); + +extern "C" TagMemoryRangeIncrementInternalFn( + *ResolveTagMemoryRangeIncrement(uint64_t hwcap, struct __ifunc_arg_t* hw)) { + if ((hwcap & _IFUNC_ARG_HWCAP) && (hw->_hwcap2 & HWCAP2_MTE)) { + return TagRegionIncrementForMTE; } -#endif + return TagRegionIncrementNoOp; +} + +extern "C" TagMemoryRangeRandomlyInternalFn( + *ResolveTagMemoryRandomly(uint64_t hwcap, struct __ifunc_arg_t* hw)) { + if ((hwcap & _IFUNC_ARG_HWCAP) && (hw->_hwcap2 & HWCAP2_MTE)) { + return TagRegionRandomlyForMTE; + } + return TagRegionRandomlyNoOp; +} + +extern "C" RemaskPtrInternalFn( + *ResolveRemaskPointer(uint64_t hwcap, struct __ifunc_arg_t* hw)) { + if ((hwcap & _IFUNC_ARG_HWCAP) && (hw->_hwcap2 & HWCAP2_MTE)) { + return RemaskVoidPtrForMTE; + } + return RemaskVoidPtrNoOp; } -RemaskPtrInternalFn* global_remask_void_ptr_fn = RemaskVoidPtrNoOp; -TagMemoryRangeIncrementInternalFn* global_tag_memory_range_increment_fn = - TagRegionIncrementNoOp; -TagMemoryRangeRandomlyInternalFn* global_tag_memory_range_randomly_fn = - TagRegionRandomlyNoOp; +void* TagMemoryRangeIncrementInternal(void* ptr, size_t size) + __attribute__((ifunc("ResolveTagMemoryRangeIncrement"))); +void* TagMemoryRangeRandomlyInternal(void* ptr, size_t size, uint64_t mask) + __attribute__((ifunc("ResolveTagMemoryRandomly"))); +void* RemaskPointerInternal(void* ptr) + __attribute__((ifunc("ResolveRemaskPointer"))); +#endif // PA_CONFIG(HAS_MEMORY_TAGGING) TagViolationReportingMode GetMemoryTaggingModeForCurrentThread() { #if PA_CONFIG(HAS_MEMORY_TAGGING) diff --git a/base/allocator/partition_allocator/tagging.h b/base/allocator/partition_allocator/tagging.h index af914452b1162..d49e062ce6319 100644 --- a/base/allocator/partition_allocator/tagging.h +++ b/base/allocator/partition_allocator/tagging.h @@ -55,32 +55,16 @@ void ChangeMemoryTaggingModeForAllThreadsPerProcess(TagViolationReportingMode); PA_COMPONENT_EXPORT(PARTITION_ALLOC) TagViolationReportingMode GetMemoryTaggingModeForCurrentThread(); -// Called by the partition allocator after initial startup, this detects MTE -// support in the current CPU and replaces the active tagging intrinsics with -// MTE versions if needed. -PA_COMPONENT_EXPORT(PARTITION_ALLOC) void InitializeMTESupportIfNeeded(); - -// These global function pointers hold the implementations of the tagging -// intrinsics (TagMemoryRangeRandomly, TagMemoryRangeIncrement, RemaskPtr). -// They are designed to be callable without taking a branch. They are initially -// set to no-op functions in tagging.cc, but can be replaced with MTE-capable -// ones through InitializeMTEIfNeeded(). This is conceptually similar to an -// IFUNC, even though less secure. These function pointers were introduced to -// support older Android releases. With the removal of support for Android M, -// it became possible to use IFUNC instead. -// TODO(bartekn): void* -> uintptr_t -using RemaskPtrInternalFn = void*(void* ptr); -using TagMemoryRangeIncrementInternalFn = void*(void* ptr, size_t size); - -using TagMemoryRangeRandomlyInternalFn = void*(void* ptr, - size_t size, - uint64_t mask); -extern PA_COMPONENT_EXPORT(PARTITION_ALLOC) - TagMemoryRangeRandomlyInternalFn* global_tag_memory_range_randomly_fn; -extern PA_COMPONENT_EXPORT(PARTITION_ALLOC) - TagMemoryRangeIncrementInternalFn* global_tag_memory_range_increment_fn; -extern PA_COMPONENT_EXPORT(PARTITION_ALLOC) - RemaskPtrInternalFn* global_remask_void_ptr_fn; +// These forward-defined functions do not really exist in tagging.cc, they're resolved +// by the dynamic linker to MTE-capable versions on the right hardware. +#if PA_CONFIG(HAS_MEMORY_TAGGING) +PA_COMPONENT_EXPORT(PARTITION_ALLOC) +void* TagMemoryRangeIncrementInternal(void* ptr, size_t size); +PA_COMPONENT_EXPORT(PARTITION_ALLOC) +void* TagMemoryRangeRandomlyInternal(void* ptr, size_t size, uint64_t mask); +PA_COMPONENT_EXPORT(PARTITION_ALLOC) +void* RemaskPointerInternal(void* ptr); +#endif // Increments the tag of the memory range ptr. Useful for provable revocations // (e.g. free). Returns the pointer with the new tag. Ensures that the entire @@ -90,7 +74,7 @@ extern PA_COMPONENT_EXPORT(PARTITION_ALLOC) template PA_ALWAYS_INLINE T* TagMemoryRangeIncrement(T* ptr, size_t size) { #if PA_CONFIG(HAS_MEMORY_TAGGING) - return reinterpret_cast(global_tag_memory_range_increment_fn(ptr, size)); + return reinterpret_cast(TagMemoryRangeIncrementInternal(ptr, size)); #else return ptr; #endif @@ -108,8 +92,7 @@ PA_ALWAYS_INLINE T* TagMemoryRangeRandomly(T* ptr, size_t size, uint64_t mask = 0u) { #if PA_CONFIG(HAS_MEMORY_TAGGING) - return reinterpret_cast( - global_tag_memory_range_randomly_fn(ptr, size, mask)); + return reinterpret_cast(TagMemoryRangeRandomlyInternal(ptr, size, mask)); #else return ptr; #endif @@ -124,7 +107,7 @@ PA_ALWAYS_INLINE void* TagMemoryRangeRandomly(uintptr_t ptr, template PA_ALWAYS_INLINE T* TagPtr(T* ptr) { #if PA_CONFIG(HAS_MEMORY_TAGGING) - return reinterpret_cast(global_remask_void_ptr_fn(ptr)); + return reinterpret_cast(RemaskPointerInternal(ptr)); #else return ptr; #endif diff --git a/base/allocator/partition_allocator/tagging_unittest.cc b/base/allocator/partition_allocator/tagging_unittest.cc index f3b8532a8f1f4..47f62ac000b43 100644 --- a/base/allocator/partition_allocator/tagging_unittest.cc +++ b/base/allocator/partition_allocator/tagging_unittest.cc @@ -16,7 +16,6 @@ namespace partition_alloc::internal { // Check whether we can call the tagging intrinsics safely on all architectures. TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeRandomlySafe) { - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); uintptr_t buffer = AllocPages(PageAllocationGranularity(), PageAllocationGranularity(), PageAccessibilityConfiguration( @@ -32,7 +31,6 @@ TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeRandomlySafe) { } TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeIncrementSafe) { - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); base::CPU cpu; uintptr_t buffer = AllocPages(PageAllocationGranularity(), PageAllocationGranularity(), @@ -54,7 +52,6 @@ TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeIncrementSafe) { #if defined(ARCH_CPU_64_BITS) // Size / alignment constraints are only enforced on 64-bit architectures. TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeBadSz) { - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); base::CPU cpu; uintptr_t buffer = AllocPages(PageAllocationGranularity(), PageAllocationGranularity(), @@ -71,7 +68,6 @@ TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeBadSz) { } TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeRandomlyNoSz) { - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); base::CPU cpu; uintptr_t buffer = AllocPages(PageAllocationGranularity(), PageAllocationGranularity(), @@ -87,7 +83,6 @@ TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeRandomlyNoSz) { } TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeRandomlyBadAlign) { - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); base::CPU cpu; uintptr_t buffer = AllocPages(PageAllocationGranularity(), PageAllocationGranularity(), @@ -104,7 +99,6 @@ TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeRandomlyBadAlign) { } TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeIncrementBadSz) { - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); base::CPU cpu; uintptr_t buffer = AllocPages(PageAllocationGranularity(), PageAllocationGranularity(), @@ -120,7 +114,6 @@ TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeIncrementBadSz) { } TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeIncrementNoSz) { - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); base::CPU cpu; uintptr_t buffer = AllocPages(PageAllocationGranularity(), PageAllocationGranularity(), @@ -136,7 +129,6 @@ TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeIncrementNoSz) { } TEST(PartitionAllocMemoryTaggingTest, TagMemoryRangeIncrementBadAlign) { - ::partition_alloc::internal::InitializeMTESupportIfNeeded(); base::CPU cpu; uintptr_t buffer = AllocPages(PageAllocationGranularity(), PageAllocationGranularity(),