about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorIvan Lozano <ivanlozano@google.com>2022-06-17 14:14:58 -0400
committerIvan Lozano <ivanlozano@google.com>2022-07-20 13:43:34 +0000
commitadf61e3b2b72f4a06b3ac5cf90d49deda42da605 (patch)
treecc7b018bca40d9d783f7b707965662da2569624f /src
parenta289cfcfb32593c63d75f113547f63ffe2dde285 (diff)
downloadrust-adf61e3b2b72f4a06b3ac5cf90d49deda42da605.tar.gz
rust-adf61e3b2b72f4a06b3ac5cf90d49deda42da605.zip
Add ShadowCallStack Support
Adds support for the LLVM ShadowCallStack sanitizer.
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md17
-rw-r--r--src/test/codegen/sanitizer_scs_attr_check.rs17
-rw-r--r--src/test/ui/invalid/invalid-no-sanitize.stderr2
-rw-r--r--src/tools/compiletest/src/header.rs3
-rw-r--r--src/tools/compiletest/src/util.rs2
5 files changed, 39 insertions, 2 deletions
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index e83c4d98cc7..9e11a154db9 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -18,11 +18,13 @@ This feature allows for use of one of following sanitizers:
 * [MemorySanitizer][clang-msan] a detector of uninitialized reads.
 * [MemTagSanitizer][clang-memtag] fast memory error detector based on
   Armv8.5-A Memory Tagging Extension.
+* [ShadowCallStack][clang-scs] provides backward-edge control flow protection.
 * [ThreadSanitizer][clang-tsan] a fast data race detector.
 
 To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
 `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`,
-`-Zsanitizer=memtag`, or `-Zsanitizer=thread`. You might also need the `--target` and `build-std` flags. Example:
+`-Zsanitizer=memtag`, `-Zsanitizer=shadow-call-stack`, or `-Zsanitizer=thread`.
+You might also need the `--target` and `build-std` flags. Example:
 ```shell
 $ RUSTFLAGS=-Zsanitizer=address cargo build -Zbuild-std --target x86_64-unknown-linux-gnu
 ```
@@ -513,6 +515,18 @@ 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).
 
+# ShadowCallStack
+
+ShadowCallStack provides backward edge control flow protection by storing a function's return address in a separately allocated 'shadow call stack' and loading the return address from that shadow call stack.
+
+ShadowCallStack requires a platform ABI which reserves `x18` as the instrumentation makes use of this register.
+
+ShadowCallStack can be enabled with `-Zsanitizer=shadow-call-stack` option and is supported on the following targets:
+
+* `aarch64-linux-android`
+
+A runtime must be provided by the application or operating system. See the [LLVM documentation][clang-scs] for further details.
+
 # ThreadSanitizer
 
 ThreadSanitizer is a data race detection tool. It is supported on the following
@@ -610,4 +624,5 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
 [clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
 [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
 [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
+[clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
 [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
diff --git a/src/test/codegen/sanitizer_scs_attr_check.rs b/src/test/codegen/sanitizer_scs_attr_check.rs
new file mode 100644
index 00000000000..0b53db3b767
--- /dev/null
+++ b/src/test/codegen/sanitizer_scs_attr_check.rs
@@ -0,0 +1,17 @@
+// This tests that the shadowcallstack attribute is
+// applied when enabling the shadow-call-stack sanitizer.
+//
+// needs-sanitizer-shadow-call-stack
+// compile-flags: -Zsanitizer=shadow-call-stack
+
+#![crate_type = "lib"]
+#![feature(no_sanitize)]
+
+// CHECK: ; Function Attrs:{{.*}}shadowcallstack
+// CHECK-NEXT: scs
+pub fn scs() {}
+
+// CHECK-NOT: ; Function Attrs:{{.*}}shadowcallstack
+// CHECK-NEXT: no_scs
+#[no_sanitize(shadow_call_stack)]
+pub fn no_scs() {}
diff --git a/src/test/ui/invalid/invalid-no-sanitize.stderr b/src/test/ui/invalid/invalid-no-sanitize.stderr
index 5a92555eb32..d328cafa00b 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`, `cfi`, `hwaddress`, `memory`, `memtag`, or `thread`
+   = note: expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, `shadow-call-stack`, 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 17f2b77dab0..37643c29d4d 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -862,6 +862,7 @@ pub fn make_test_description<R: Read>(
     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);
+    let has_shadow_call_stack = util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(&&*config.target);
     // for `-Z gcc-ld=lld`
     let has_rust_lld = config
         .compile_lib_path
@@ -899,6 +900,8 @@ pub fn make_test_description<R: Read>(
         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 |= !has_shadow_call_stack
+            && config.parse_name_directive(ln, "needs-sanitizer-shadow-call-stack");
         ignore |= config.target_panic == PanicStrategy::Abort
             && config.parse_name_directive(ln, "needs-unwind");
         ignore |= config.target == "wasm32-unknown-unknown"
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 215af347f17..102b9308dc9 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -121,6 +121,8 @@ pub const HWASAN_SUPPORTED_TARGETS: &[&str] =
 pub const MEMTAG_SUPPORTED_TARGETS: &[&str] =
     &["aarch64-linux-android", "aarch64-unknown-linux-gnu"];
 
+pub const SHADOWCALLSTACK_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-android"];
+
 const BIG_ENDIAN: &[&str] = &[
     "aarch64_be",
     "armebv7r",