llvm.org GIT mirror llvm / 8060f84
ARM MTE stack sanitizer. Add "memtag" sanitizer that detects and mitigates stack memory issues using armv8.5 Memory Tagging Extension. It is similar in principle to HWASan, which is a software implementation of the same idea, but there are enough differencies to warrant a new sanitizer type IMHO. It is also expected to have very different performance properties. The new sanitizer does not have a runtime library (it may grow one later, along with a "debugging" mode). Similar to SafeStack and StackProtector, the instrumentation pass (in a follow up change) will be inserted in all cases, but will only affect functions marked with the new sanitize_memtag attribute. Reviewers: pcc, hctim, vitalybuka, ostannard Subscribers: srhines, mehdi_amini, javed.absar, kristof.beyls, hiraditya, cryptoad, steven_wu, dexonsmith, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D64169 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366123 91177308-0d34-0410-b5e6-96231b3b80d8 Evgeniy Stepanov a month ago
16 changed file(s) with 71 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
10561056 * code 56: ``nocf_check``
10571057 * code 57: ``optforfuzzing``
10581058 * code 58: ``shadowcallstack``
1059 * code 64: ``sanitize_memtag``
10591060
10601061 .. note::
10611062 The ``allocsize`` attribute has a special encoding for its arguments. Its two
16791679 ``sanitize_hwaddress``
16801680 This attribute indicates that HWAddressSanitizer checks
16811681 (dynamic address safety analysis based on tagged pointers) are enabled for
1682 this function.
1683 ``sanitize_memtag``
1684 This attribute indicates that MemTagSanitizer checks
1685 (dynamic address safety analysis based on Armv8 MTE) are enabled for
16821686 this function.
16831687 ``speculative_load_hardening``
16841688 This attribute indicates that
629629 ATTR_KIND_IMMARG = 60,
630630 ATTR_KIND_WILLRETURN = 61,
631631 ATTR_KIND_NOFREE = 62,
632 ATTR_KIND_NOSYNC = 63
632 ATTR_KIND_NOSYNC = 63,
633 ATTR_KIND_SANITIZE_MEMTAG = 64,
633634 };
634635
635636 enum ComdatSelectionKindCodes {
183183
184184 /// HWAddressSanitizer is on.
185185 def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress">;
186
187 /// MemTagSanitizer is on.
188 def SanitizeMemTag : EnumAttr<"sanitize_memtag">;
186189
187190 /// Speculative Load Hardening is enabled.
188191 ///
232235 def : CompatRule<"isEqual">;
233236 def : CompatRule<"isEqual">;
234237 def : CompatRule<"isEqual">;
238 def : CompatRule<"isEqual">;
235239 def : CompatRule<"isEqual">;
236240 def : CompatRule<"isEqual">;
237241
678678 KEYWORD(shadowcallstack);
679679 KEYWORD(sanitize_address);
680680 KEYWORD(sanitize_hwaddress);
681 KEYWORD(sanitize_memtag);
681682 KEYWORD(sanitize_thread);
682683 KEYWORD(sanitize_memory);
683684 KEYWORD(speculative_load_hardening);
13101310 B.addAttribute(Attribute::SanitizeAddress); break;
13111311 case lltok::kw_sanitize_hwaddress:
13121312 B.addAttribute(Attribute::SanitizeHWAddress); break;
1313 case lltok::kw_sanitize_memtag:
1314 B.addAttribute(Attribute::SanitizeMemTag); break;
13131315 case lltok::kw_sanitize_thread:
13141316 B.addAttribute(Attribute::SanitizeThread); break;
13151317 case lltok::kw_sanitize_memory:
16671669 case lltok::kw_returns_twice:
16681670 case lltok::kw_sanitize_address:
16691671 case lltok::kw_sanitize_hwaddress:
1672 case lltok::kw_sanitize_memtag:
16701673 case lltok::kw_sanitize_memory:
16711674 case lltok::kw_sanitize_thread:
16721675 case lltok::kw_speculative_load_hardening:
17651768 case lltok::kw_returns_twice:
17661769 case lltok::kw_sanitize_address:
17671770 case lltok::kw_sanitize_hwaddress:
1771 case lltok::kw_sanitize_memtag:
17681772 case lltok::kw_sanitize_memory:
17691773 case lltok::kw_sanitize_thread:
17701774 case lltok::kw_speculative_load_hardening:
175175 kw_argmemonly,
176176 kw_sanitize_address,
177177 kw_sanitize_hwaddress,
178 kw_sanitize_memtag,
178179 kw_builtin,
179180 kw_byval,
180181 kw_inalloca,
12951295 case Attribute::AllocSize:
12961296 llvm_unreachable("allocsize not supported in raw format");
12971297 break;
1298 case Attribute::SanitizeMemTag:
1299 llvm_unreachable("sanitize_memtag attribute not supported in raw format");
1300 break;
12981301 }
12991302 llvm_unreachable("Unsupported attribute type");
13001303 }
13041307
13051308 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
13061309 I = Attribute::AttrKind(I + 1)) {
1307 if (I == Attribute::Dereferenceable ||
1310 if (I == Attribute::SanitizeMemTag ||
1311 I == Attribute::Dereferenceable ||
13081312 I == Attribute::DereferenceableOrNull ||
13091313 I == Attribute::ArgMemOnly ||
13101314 I == Attribute::AllocSize ||
15331537 return Attribute::ZExt;
15341538 case bitc::ATTR_KIND_IMMARG:
15351539 return Attribute::ImmArg;
1540 case bitc::ATTR_KIND_SANITIZE_MEMTAG:
1541 return Attribute::SanitizeMemTag;
15361542 }
15371543 }
15381544
722722 return bitc::ATTR_KIND_Z_EXT;
723723 case Attribute::ImmArg:
724724 return bitc::ATTR_KIND_IMMARG;
725 case Attribute::SanitizeMemTag:
726 return bitc::ATTR_KIND_SANITIZE_MEMTAG;
725727 case Attribute::EndAttrKinds:
726728 llvm_unreachable("Can not encode end-attribute kinds marker.");
727729 case Attribute::None:
282282 return "sanitize_address";
283283 if (hasAttribute(Attribute::SanitizeHWAddress))
284284 return "sanitize_hwaddress";
285 if (hasAttribute(Attribute::SanitizeMemTag))
286 return "sanitize_memtag";
285287 if (hasAttribute(Attribute::AlwaysInline))
286288 return "alwaysinline";
287289 if (hasAttribute(Attribute::ArgMemOnly))
15151515 case Attribute::ReturnsTwice:
15161516 case Attribute::SanitizeAddress:
15171517 case Attribute::SanitizeHWAddress:
1518 case Attribute::SanitizeMemTag:
15181519 case Attribute::SanitizeThread:
15191520 case Attribute::SanitizeMemory:
15201521 case Attribute::MinSize:
5656 .Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
5757 .Case("sanitize_memory", Attribute::SanitizeMemory)
5858 .Case("sanitize_thread", Attribute::SanitizeThread)
59 .Case("sanitize_memtag", Attribute::SanitizeMemTag)
5960 .Case("speculative_load_hardening", Attribute::SpeculativeLoadHardening)
6061 .Case("ssp", Attribute::StackProtect)
6162 .Case("sspreq", Attribute::StackProtectReq)
849849 case Attribute::SanitizeMemory:
850850 case Attribute::SanitizeThread:
851851 case Attribute::SanitizeHWAddress:
852 case Attribute::SanitizeMemTag:
852853 case Attribute::SpeculativeLoadHardening:
853854 case Attribute::StackProtect:
854855 case Attribute::StackProtectReq:
203203 ; CHECK: define void @f34()
204204 {
205205 call void @nobuiltin() nobuiltin
206 ; CHECK: call void @nobuiltin() #39
206 ; CHECK: call void @nobuiltin() #40
207207 ret void;
208208 }
209209
365365 define void @f62() nosync
366366 {
367367 ret void
368 }
369
370 ; CHECK: define void @f63() #39
371 define void @f63() sanitize_memtag
372 {
373 ret void;
368374 }
369375
370376 ; CHECK: attributes #0 = { noreturn }
406412 ; CHECK: attributes #36 = { willreturn }
407413 ; CHECK: attributes #37 = { nofree }
408414 ; CHECK: attributes #38 = { nosync }
409 ; CHECK: attributes #39 = { nobuiltin }
415 ; CHECK: attributes #39 = { sanitize_memtag }
416 ; CHECK: attributes #40 = { nobuiltin }
2121 ret i32 %i
2222 }
2323
24 define i32 @sanitize_memtag_callee(i32 %i) sanitize_memtag {
25 ret i32 %i
26 }
27
2428 define i32 @safestack_callee(i32 %i) safestack {
2529 ret i32 %i
2630 }
4650 }
4751
4852 define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory {
53 ret i32 %i
54 }
55
56 define i32 @alwaysinline_sanitize_memtag_callee(i32 %i) alwaysinline sanitize_memtag {
4957 ret i32 %i
5058 }
5159
103111 ; CHECK-NEXT: ret i32
104112 }
105113
114 define i32 @test_no_sanitize_memtag(i32 %arg) {
115 %x1 = call i32 @noattr_callee(i32 %arg)
116 %x2 = call i32 @sanitize_memtag_callee(i32 %x1)
117 %x3 = call i32 @alwaysinline_callee(i32 %x2)
118 %x4 = call i32 @alwaysinline_sanitize_memtag_callee(i32 %x3)
119 ret i32 %x4
120 ; CHECK-LABEL: @test_no_sanitize_memtag(
121 ; CHECK-NEXT: @sanitize_memtag_callee
122 ; CHECK-NEXT: ret i32
123 }
124
106125
107126 ; Check that:
108127 ; * noattr callee is not inlined into sanitize_(address|memory|thread) caller,
149168 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
150169 ret i32 %x4
151170 ; CHECK-LABEL: @test_sanitize_thread(
171 ; CHECK-NEXT: @noattr_callee
172 ; CHECK-NEXT: ret i32
173 }
174
175 define i32 @test_sanitize_memtag(i32 %arg) sanitize_memtag {
176 %x1 = call i32 @noattr_callee(i32 %arg)
177 %x2 = call i32 @sanitize_memtag_callee(i32 %x1)
178 %x3 = call i32 @alwaysinline_callee(i32 %x2)
179 %x4 = call i32 @alwaysinline_sanitize_memtag_callee(i32 %x3)
180 ret i32 %x4
181 ; CHECK-LABEL: @test_sanitize_memtag(
152182 ; CHECK-NEXT: @noattr_callee
153183 ; CHECK-NEXT: ret i32
154184 }
2525 "inaccessiblemem_or_argmemonly" "inlinehint" "jumptable" "minsize" "naked" "nobuiltin"
2626 "noduplicate" "noimplicitfloat" "noinline" "nonlazybind" "noredzone" "noreturn"
2727 "norecurse" "nounwind" "optnone" "optsize" "readnone" "readonly" "returns_twice"
28 "speculatable" "ssp" "sspreq" "sspstrong" "safestack" "sanitize_address" "sanitize_hwaddress"
28 "speculatable" "ssp" "sspreq" "sspstrong" "safestack" "sanitize_address" "sanitize_hwaddress" "sanitize_memtag"
2929 "sanitize_thread" "sanitize_memory" "strictfp" "uwtable" "writeonly" "immarg") 'symbols) . font-lock-constant-face)
3030 ;; Variables
3131 '("%[-a-zA-Z$._][-a-zA-Z$._0-9]*" . font-lock-variable-name-face)