about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp2
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_linux_android.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_typeck/src/collect.rs4
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md20
-rw-r--r--src/test/codegen/sanitizer_memtag_attr_check.rs12
-rw-r--r--src/test/ui/invalid/invalid-no-sanitize.stderr2
-rw-r--r--src/tools/compiletest/src/header.rs2
-rw-r--r--src/tools/compiletest/src/util.rs3
15 files changed, 67 insertions, 6 deletions
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 30a52d6bd67..f6d7221d4e9 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -55,6 +55,19 @@ pub fn sanitize<'ll>(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &
     if enabled.contains(SanitizerSet::HWADDRESS) {
         llvm::Attribute::SanitizeHWAddress.apply_llfn(Function, llfn);
     }
+    if enabled.contains(SanitizerSet::MEMTAG) {
+        // Check to make sure the mte target feature is actually enabled.
+        let sess = cx.tcx.sess;
+        let features = llvm_util::llvm_global_features(sess).join(",");
+        let mte_feature_enabled = features.rfind("+mte");
+        let mte_feature_disabled = features.rfind("-mte");
+
+        if mte_feature_enabled.is_none() || (mte_feature_disabled > mte_feature_enabled) {
+            sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
+        }
+
+        llvm::Attribute::SanitizeMemTag.apply_llfn(Function, llfn);
+    }
 }
 
 /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 90d4367a280..657f1fcf31e 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -190,6 +190,7 @@ pub enum Attribute {
     StackProtectStrong = 31,
     StackProtect = 32,
     NoUndef = 33,
+    SanitizeMemTag = 34,
 }
 
 /// LLVMIntPredicate
diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
index 9e0a9b354e1..a2b0e9b4d29 100644
--- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
+++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
@@ -83,6 +83,7 @@ enum LLVMRustAttribute {
   StackProtectStrong = 31,
   StackProtect = 32,
   NoUndef = 33,
+  SanitizeMemTag = 34,
 };
 
 typedef struct OpaqueRustString *RustStringRef;
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 23333199506..c8f31adbfd9 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -226,6 +226,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
     return Attribute::StackProtect;
   case NoUndef:
     return Attribute::NoUndef;
+  case SanitizeMemTag:
+    return Attribute::SanitizeMemTag;
   }
   report_fatal_error("bad AttributeKind");
 }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index c069144fa9f..0a4bd23937d 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -376,7 +376,7 @@ mod desc {
     pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
     pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
-    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory` or `thread`";
+    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory`, `memtag`, or `thread`";
     pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
     pub const parse_cfguard: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -639,6 +639,7 @@ mod parse {
                     "cfi" => SanitizerSet::CFI,
                     "leak" => SanitizerSet::LEAK,
                     "memory" => SanitizerSet::MEMORY,
+                    "memtag" => SanitizerSet::MEMTAG,
                     "thread" => SanitizerSet::THREAD,
                     "hwaddress" => SanitizerSet::HWADDRESS,
                     _ => return false,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 33140911f91..5220c884644 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -876,6 +876,7 @@ symbols! {
         mem_zeroed,
         member_constraints,
         memory,
+        memtag,
         message,
         meta,
         metadata_type,
diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs
index 1e9abbbe1e7..5692925f63b 100644
--- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs
@@ -14,7 +14,9 @@ pub fn target() -> Target {
             // As documented in https://developer.android.com/ndk/guides/cpu-features.html
             // the neon (ASIMD) and FP must exist on all android aarch64 targets.
             features: "+neon,+fp-armv8".to_string(),
-            supported_sanitizers: SanitizerSet::CFI | SanitizerSet::HWADDRESS,
+            supported_sanitizers: SanitizerSet::CFI
+                | SanitizerSet::HWADDRESS
+                | SanitizerSet::MEMTAG,
             ..super::android_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
index 850381f7fb0..974a5b84d1d 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
@@ -14,6 +14,7 @@ pub fn target() -> Target {
                 | SanitizerSet::CFI
                 | SanitizerSet::LEAK
                 | SanitizerSet::MEMORY
+                | SanitizerSet::MEMTAG
                 | SanitizerSet::THREAD
                 | SanitizerSet::HWADDRESS,
             ..super::linux_gnu_base::opts()
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index bfafe2d83d7..92678aed5b1 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -606,6 +606,7 @@ bitflags::bitflags! {
         const THREAD  = 1 << 3;
         const HWADDRESS = 1 << 4;
         const CFI     = 1 << 5;
+        const MEMTAG  = 1 << 6;
     }
 }
 
@@ -619,6 +620,7 @@ impl SanitizerSet {
             SanitizerSet::CFI => "cfi",
             SanitizerSet::LEAK => "leak",
             SanitizerSet::MEMORY => "memory",
+            SanitizerSet::MEMTAG => "memtag",
             SanitizerSet::THREAD => "thread",
             SanitizerSet::HWADDRESS => "hwaddress",
             _ => return None,
@@ -652,6 +654,7 @@ impl IntoIterator for SanitizerSet {
             SanitizerSet::CFI,
             SanitizerSet::LEAK,
             SanitizerSet::MEMORY,
+            SanitizerSet::MEMTAG,
             SanitizerSet::THREAD,
             SanitizerSet::HWADDRESS,
         ]
@@ -1883,6 +1886,7 @@ impl Target {
                                 Some("cfi") => SanitizerSet::CFI,
                                 Some("leak") => SanitizerSet::LEAK,
                                 Some("memory") => SanitizerSet::MEMORY,
+                                Some("memtag") => SanitizerSet::MEMTAG,
                                 Some("thread") => SanitizerSet::THREAD,
                                 Some("hwaddress") => SanitizerSet::HWADDRESS,
                                 Some(s) => return Err(format!("unknown sanitizer {}", s)),
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 4c9f21d0d4a..18f54eb2246 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -3009,6 +3009,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
                     } else if item.has_name(sym::memory) {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
+                    } else if item.has_name(sym::memtag) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG;
                     } else if item.has_name(sym::thread) {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
                     } else if item.has_name(sym::hwaddress) {
@@ -3016,7 +3018,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                     } else {
                         tcx.sess
                             .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
-                            .note("expected one of: `address`, `hwaddress`, `memory` or `thread`")
+                            .note("expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, or `thread`")
                             .emit();
                     }
                 }
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index d630f4ecb7b..457851b0cc7 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -16,11 +16,13 @@ This feature allows for use of one of following sanitizers:
   AddressSanitizer, but based on partial hardware assistance.
 * [LeakSanitizer][clang-lsan] a run-time memory leak detector.
 * [MemorySanitizer][clang-msan] a detector of uninitialized reads.
+* [MemTagSanitizer][clang-memtag] fast memory error detector based on
+  Armv8.5-A Memory Tagging Extension.
 * [ThreadSanitizer][clang-tsan] a fast data race detector.
 
 To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
-`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory` or
-`-Zsanitizer=thread`.
+`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`,
+`-Zsanitizer=memtag`, or `-Zsanitizer=thread`.
 
 # AddressSanitizer
 
@@ -494,6 +496,20 @@ $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
     #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
 ```
 
+# MemTagSanitizer
+
+MemTagSanitizer detects a similar class of errors as AddressSanitizer and HardwareAddressSanitizer, but with lower overhead suitable for use as hardening for production binaries.
+
+MemTagSanitizer is supported on the following targets:
+
+* `aarch64-linux-android`
+* `aarch64-unknown-linux-gnu`
+
+MemTagSanitizer requires hardware support and the `mte` target feature.
+To enable this target feature compile with `-C target-feature="+mte"`.
+
+More information can be found in the associated [LLVM documentation](https://llvm.org/docs/MemTagSanitizer.html).
+
 # ThreadSanitizer
 
 ThreadSanitizer is a data race detection tool. It is supported on the following
diff --git a/src/test/codegen/sanitizer_memtag_attr_check.rs b/src/test/codegen/sanitizer_memtag_attr_check.rs
new file mode 100644
index 00000000000..2fd362656d4
--- /dev/null
+++ b/src/test/codegen/sanitizer_memtag_attr_check.rs
@@ -0,0 +1,12 @@
+// This tests that the sanitize_memtag attribute is
+// applied when enabling the memtag sanitizer.
+//
+// needs-sanitizer-memtag
+// compile-flags: -Zsanitizer=memtag -Ctarget-feature=+mte
+
+#![crate_type = "lib"]
+
+// CHECK: ; Function Attrs:{{.*}}sanitize_memtag
+pub fn tagged() {}
+
+// CHECK: attributes #0 = {{.*}}sanitize_memtag
diff --git a/src/test/ui/invalid/invalid-no-sanitize.stderr b/src/test/ui/invalid/invalid-no-sanitize.stderr
index 4c0b17c7d37..5a92555eb32 100644
--- a/src/test/ui/invalid/invalid-no-sanitize.stderr
+++ b/src/test/ui/invalid/invalid-no-sanitize.stderr
@@ -4,7 +4,7 @@ error: invalid argument for `no_sanitize`
 LL | #[no_sanitize(brontosaurus)]
    |               ^^^^^^^^^^^^
    |
-   = note: expected one of: `address`, `hwaddress`, `memory` or `thread`
+   = note: expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, or `thread`
 
 error: aborting due to previous error
 
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index da7a19139c6..60c94eff47a 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -863,6 +863,7 @@ pub fn make_test_description<R: Read>(
     let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
+    let has_memtag = util::MEMTAG_SUPPORTED_TARGETS.contains(&&*config.target);
     // for `-Z gcc-ld=lld`
     let has_rust_lld = config
         .compile_lib_path
@@ -899,6 +900,7 @@ pub fn make_test_description<R: Read>(
         ignore |= !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory");
         ignore |= !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread");
         ignore |= !has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress");
+        ignore |= !has_memtag && config.parse_name_directive(ln, "needs-sanitizer-memtag");
         ignore |= config.target_panic == PanicStrategy::Abort
             && config.parse_name_directive(ln, "needs-unwind");
         ignore |= config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln);
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 6ca145a58e9..bed509d77be 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -117,6 +117,9 @@ pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[
 pub const HWASAN_SUPPORTED_TARGETS: &[&str] =
     &["aarch64-linux-android", "aarch64-unknown-linux-gnu"];
 
+pub const MEMTAG_SUPPORTED_TARGETS: &[&str] =
+    &["aarch64-linux-android", "aarch64-unknown-linux-gnu"];
+
 const BIG_ENDIAN: &[&str] = &[
     "aarch64_be",
     "armebv7r",