Skip to content

Commit 0bb72a2

Browse files
authored
Rollup merge of rust-lang#91675 - ivanloz:memtagsan, r=nagisa
Add MemTagSanitizer Support Add support for the LLVM [MemTagSanitizer](https://llvm.org/docs/MemTagSanitizer.html). On hardware which supports it (see caveats below), the MemTagSanitizer can catch bugs similar to AddressSanitizer and HardwareAddressSanitizer, but with lower overhead. On a tag mismatch, a SIGSEGV is signaled with code SEGV_MTESERR / SEGV_MTEAERR. # Usage `-Zsanitizer=memtag -C target-feature="+mte"` # Comments/Caveats * MemTagSanitizer is only supported on AArch64 targets with hardware support * Requires `-C target-feature="+mte"` * LLVM MemTagSanitizer currently only performs stack tagging. # TODO * Tests * Example
2 parents f8b83a2 + 568aeda commit 0bb72a2

File tree

15 files changed

+67
-6
lines changed

15 files changed

+67
-6
lines changed

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ pub fn sanitize<'ll>(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &
5555
if enabled.contains(SanitizerSet::HWADDRESS) {
5656
llvm::Attribute::SanitizeHWAddress.apply_llfn(Function, llfn);
5757
}
58+
if enabled.contains(SanitizerSet::MEMTAG) {
59+
// Check to make sure the mte target feature is actually enabled.
60+
let sess = cx.tcx.sess;
61+
let features = llvm_util::llvm_global_features(sess).join(",");
62+
let mte_feature_enabled = features.rfind("+mte");
63+
let mte_feature_disabled = features.rfind("-mte");
64+
65+
if mte_feature_enabled.is_none() || (mte_feature_disabled > mte_feature_enabled) {
66+
sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
67+
}
68+
69+
llvm::Attribute::SanitizeMemTag.apply_llfn(Function, llfn);
70+
}
5871
}
5972

6073
/// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ pub enum Attribute {
190190
StackProtectStrong = 31,
191191
StackProtect = 32,
192192
NoUndef = 33,
193+
SanitizeMemTag = 34,
193194
}
194195

195196
/// LLVMIntPredicate

compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ enum LLVMRustAttribute {
8383
StackProtectStrong = 31,
8484
StackProtect = 32,
8585
NoUndef = 33,
86+
SanitizeMemTag = 34,
8687
};
8788

8889
typedef struct OpaqueRustString *RustStringRef;

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
226226
return Attribute::StackProtect;
227227
case NoUndef:
228228
return Attribute::NoUndef;
229+
case SanitizeMemTag:
230+
return Attribute::SanitizeMemTag;
229231
}
230232
report_fatal_error("bad AttributeKind");
231233
}

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ mod desc {
376376
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
377377
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
378378
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
379-
pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory` or `thread`";
379+
pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory`, `memtag`, or `thread`";
380380
pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
381381
pub const parse_cfguard: &str =
382382
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -639,6 +639,7 @@ mod parse {
639639
"cfi" => SanitizerSet::CFI,
640640
"leak" => SanitizerSet::LEAK,
641641
"memory" => SanitizerSet::MEMORY,
642+
"memtag" => SanitizerSet::MEMTAG,
642643
"thread" => SanitizerSet::THREAD,
643644
"hwaddress" => SanitizerSet::HWADDRESS,
644645
_ => return false,

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ symbols! {
876876
mem_zeroed,
877877
member_constraints,
878878
memory,
879+
memtag,
879880
message,
880881
meta,
881882
metadata_type,

compiler/rustc_target/src/spec/aarch64_linux_android.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ pub fn target() -> Target {
1414
// As documented in https://developer.android.com/ndk/guides/cpu-features.html
1515
// the neon (ASIMD) and FP must exist on all android aarch64 targets.
1616
features: "+neon,+fp-armv8".to_string(),
17-
supported_sanitizers: SanitizerSet::CFI | SanitizerSet::HWADDRESS,
17+
supported_sanitizers: SanitizerSet::CFI
18+
| SanitizerSet::HWADDRESS
19+
| SanitizerSet::MEMTAG,
1820
..super::android_base::opts()
1921
},
2022
}

compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub fn target() -> Target {
1414
| SanitizerSet::CFI
1515
| SanitizerSet::LEAK
1616
| SanitizerSet::MEMORY
17+
| SanitizerSet::MEMTAG
1718
| SanitizerSet::THREAD
1819
| SanitizerSet::HWADDRESS,
1920
..super::linux_gnu_base::opts()

compiler/rustc_target/src/spec/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ bitflags::bitflags! {
606606
const THREAD = 1 << 3;
607607
const HWADDRESS = 1 << 4;
608608
const CFI = 1 << 5;
609+
const MEMTAG = 1 << 6;
609610
}
610611
}
611612

@@ -619,6 +620,7 @@ impl SanitizerSet {
619620
SanitizerSet::CFI => "cfi",
620621
SanitizerSet::LEAK => "leak",
621622
SanitizerSet::MEMORY => "memory",
623+
SanitizerSet::MEMTAG => "memtag",
622624
SanitizerSet::THREAD => "thread",
623625
SanitizerSet::HWADDRESS => "hwaddress",
624626
_ => return None,
@@ -652,6 +654,7 @@ impl IntoIterator for SanitizerSet {
652654
SanitizerSet::CFI,
653655
SanitizerSet::LEAK,
654656
SanitizerSet::MEMORY,
657+
SanitizerSet::MEMTAG,
655658
SanitizerSet::THREAD,
656659
SanitizerSet::HWADDRESS,
657660
]
@@ -1883,6 +1886,7 @@ impl Target {
18831886
Some("cfi") => SanitizerSet::CFI,
18841887
Some("leak") => SanitizerSet::LEAK,
18851888
Some("memory") => SanitizerSet::MEMORY,
1889+
Some("memtag") => SanitizerSet::MEMTAG,
18861890
Some("thread") => SanitizerSet::THREAD,
18871891
Some("hwaddress") => SanitizerSet::HWADDRESS,
18881892
Some(s) => return Err(format!("unknown sanitizer {}", s)),

compiler/rustc_typeck/src/collect.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3009,14 +3009,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
30093009
codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
30103010
} else if item.has_name(sym::memory) {
30113011
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
3012+
} else if item.has_name(sym::memtag) {
3013+
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
30123014
} else if item.has_name(sym::thread) {
30133015
codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
30143016
} else if item.has_name(sym::hwaddress) {
30153017
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS;
30163018
} else {
30173019
tcx.sess
30183020
.struct_span_err(item.span(), "invalid argument for `no_sanitize`")
3019-
.note("expected one of: `address`, `hwaddress`, `memory` or `thread`")
3021+
.note("expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, or `thread`")
30203022
.emit();
30213023
}
30223024
}

0 commit comments

Comments
 (0)