xref: /aosp_15_r20/external/cronet/base/allocator/partition_allocator/src/partition_alloc/tagging.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef PARTITION_ALLOC_TAGGING_H_
6 #define PARTITION_ALLOC_TAGGING_H_
7 
8 // This file contains method definitions to support Armv8.5-A's memory tagging
9 // extension.
10 
11 #include <cstddef>
12 #include <cstdint>
13 
14 #include "build/build_config.h"
15 #include "partition_alloc/partition_alloc_base/compiler_specific.h"
16 #include "partition_alloc/partition_alloc_base/component_export.h"
17 #include "partition_alloc/partition_alloc_buildflags.h"
18 #include "partition_alloc/partition_alloc_config.h"
19 
20 #if BUILDFLAG(HAS_MEMORY_TAGGING) && BUILDFLAG(IS_ANDROID)
21 #include <csignal>
22 #endif
23 
24 namespace partition_alloc {
25 
26 // Enum configures Arm's MTE extension to operate in different modes
27 enum class TagViolationReportingMode {
28   // Default settings
29   kUndefined,
30   // MTE explicitly disabled.
31   kDisabled,
32   // Precise tag violation reports, higher overhead. Good for unittests
33   // and security critical threads.
34   kSynchronous,
35   // Imprecise tag violation reports (async mode). Lower overhead.
36   kAsynchronous,
37 };
38 
39 // Changes the memory tagging mode for the calling thread.
40 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
41 void ChangeMemoryTaggingModeForCurrentThread(TagViolationReportingMode);
42 
43 namespace internal {
44 
45 constexpr uint64_t kMemTagGranuleSize = 16u;
46 #if BUILDFLAG(HAS_MEMORY_TAGGING)
47 constexpr uint64_t kPtrTagMask = 0xff00000000000000uLL;
48 #else
49 constexpr uint64_t kPtrTagMask = 0;
50 #endif  // BUILDFLAG(HAS_MEMORY_TAGGING)
51 constexpr uint64_t kPtrUntagMask = ~kPtrTagMask;
52 
53 #if BUILDFLAG(IS_ANDROID)
54 // Changes the memory tagging mode for all threads in the current process.
55 // Returns true on success. Most likely reason for failure is because heap
56 // tagging may not be re-enabled after being disabled.
57 // https://android.googlesource.com/platform/bionic/+/446b4dde724ee64a336a78188c3c9a15aebca87c/libc/include/malloc.h#235
58 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
59 bool ChangeMemoryTaggingModeForAllThreadsPerProcess(TagViolationReportingMode);
60 #endif
61 
62 // Gets the memory tagging mode for the calling thread. Returns kUndefined if
63 // MTE support is not available.
64 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
65 TagViolationReportingMode GetMemoryTaggingModeForCurrentThread();
66 
67 // These forward-defined functions do not really exist in tagging.cc, they're
68 // resolved by the dynamic linker to MTE-capable versions on the right hardware.
69 #if BUILDFLAG(HAS_MEMORY_TAGGING)
70 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
71 void* TagMemoryRangeIncrementInternal(void* ptr, size_t size);
72 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
73 void* TagMemoryRangeRandomlyInternal(void* ptr, size_t size, uint64_t mask);
74 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
75 void* RemaskPointerInternal(void* ptr);
76 #endif  // BUILDFLAG(HAS_MEMORY_TAGGING)
77 
78 // Increments the tag of the memory range ptr. Useful for provable revocations
79 // (e.g. free). Returns the pointer with the new tag. Ensures that the entire
80 // range is set to the same tag.
TagMemoryRangeIncrement(void * ptr,size_t size)81 PA_ALWAYS_INLINE void* TagMemoryRangeIncrement(void* ptr, size_t size) {
82 #if BUILDFLAG(HAS_MEMORY_TAGGING)
83   return TagMemoryRangeIncrementInternal(ptr, size);
84 #else
85   return ptr;
86 #endif  // BUILDFLAG(HAS_MEMORY_TAGGING)
87 }
88 
TagMemoryRangeIncrement(uintptr_t address,size_t size)89 PA_ALWAYS_INLINE void* TagMemoryRangeIncrement(uintptr_t address, size_t size) {
90   return TagMemoryRangeIncrement(reinterpret_cast<void*>(address), size);
91 }
92 
93 // Randomly changes the tag of the ptr memory range. Useful for initial random
94 // initialization. Returns the pointer with the new tag. Ensures that the entire
95 // range is set to the same tag.
96 PA_ALWAYS_INLINE void* TagMemoryRangeRandomly(uintptr_t address,
97                                               size_t size,
98                                               uint64_t mask = 0u) {
99   void* ptr = reinterpret_cast<void*>(address);
100 #if BUILDFLAG(HAS_MEMORY_TAGGING)
101   return reinterpret_cast<void*>(
102       TagMemoryRangeRandomlyInternal(ptr, size, mask));
103 #else
104   return ptr;
105 #endif  // BUILDFLAG(HAS_MEMORY_TAGGING)
106 }
107 
108 // Gets a version of ptr that's safe to dereference.
109 template <typename T>
TagPtr(T * ptr)110 PA_ALWAYS_INLINE T* TagPtr(T* ptr) {
111 #if BUILDFLAG(HAS_MEMORY_TAGGING)
112   return reinterpret_cast<T*>(RemaskPointerInternal(ptr));
113 #else
114   return ptr;
115 #endif  // BUILDFLAG(HAS_MEMORY_TAGGING)
116 }
117 
118 // Gets a version of |address| that's safe to dereference, and casts to a
119 // pointer.
TagAddr(uintptr_t address)120 PA_ALWAYS_INLINE void* TagAddr(uintptr_t address) {
121   return TagPtr(reinterpret_cast<void*>(address));
122 }
123 
124 // Strips the tag bits off |address|.
UntagAddr(uintptr_t address)125 PA_ALWAYS_INLINE uintptr_t UntagAddr(uintptr_t address) {
126 #if BUILDFLAG(HAS_MEMORY_TAGGING)
127   return address & internal::kPtrUntagMask;
128 #else
129   return address;
130 #endif  // BUILDFLAG(HAS_MEMORY_TAGGING)
131 }
132 
133 }  // namespace internal
134 
135 // Strips the tag bits off |ptr|.
136 template <typename T>
UntagPtr(T * ptr)137 PA_ALWAYS_INLINE uintptr_t UntagPtr(T* ptr) {
138   return internal::UntagAddr(reinterpret_cast<uintptr_t>(ptr));
139 }
140 
141 #if BUILDFLAG(HAS_MEMORY_TAGGING) && BUILDFLAG(IS_ANDROID)
PA_COMPONENT_EXPORT(PARTITION_ALLOC)142 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PermissiveMte {
143  public:
144   static void SetEnabled(bool enabled);
145   static bool HandleCrash(int signo, siginfo_t* siginfo, ucontext_t* context);
146 
147  private:
148   static bool enabled_;
149 };
150 #endif  // BUILDFLAG(HAS_MEMORY_TAGGING)
151 
152 }  // namespace partition_alloc
153 
154 #endif  // PARTITION_ALLOC_TAGGING_H_
155