diff options
| author | bors <bors@rust-lang.org> | 2023-05-28 04:41:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-05-28 04:41:13 +0000 |
| commit | 2560b80a08597e4192aa3ee5a4670e36a5e4a7dd (patch) | |
| tree | ec75c4a52fa5946872d23a4cc34216d775700e3e /src | |
| parent | b9c5fdc888e05be88269a47d40fd0d911ec2be0b (diff) | |
| parent | 019d75b44e3f4349495890453d2d154a8f7ba116 (diff) | |
| download | rust-2560b80a08597e4192aa3ee5a4670e36a5e4a7dd.tar.gz rust-2560b80a08597e4192aa3ee5a4670e36a5e4a7dd.zip | |
Auto merge of #112000 - wesleywiser:safestack, r=Amanieu
Add support for LLVM SafeStack Adds support for LLVM [SafeStack] which provides backward edge control flow protection by separating the stack into two parts: data which is only accessed in provable safe ways is allocated on the normal stack (the "safe stack") and all other data is placed in a separate allocation (the "unsafe stack"). SafeStack support is enabled by passing `-Zsanitizer=safestack`. [SafeStack]: https://clang.llvm.org/docs/SafeStack.html cc `@rcvalle` #39699
Diffstat (limited to 'src')
| -rw-r--r-- | src/bootstrap/llvm.rs | 2 | ||||
| -rw-r--r-- | src/doc/rustc/src/exploit-mitigations.md | 119 | ||||
| -rw-r--r-- | src/doc/unstable-book/src/compiler-flags/sanitizer.md | 14 | ||||
| -rw-r--r-- | src/tools/compiletest/src/header/needs.rs | 7 | ||||
| -rw-r--r-- | src/tools/compiletest/src/util.rs | 2 |
5 files changed, 54 insertions, 90 deletions
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 040a12f5d10..3fd0cca40e5 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -1017,7 +1017,7 @@ fn supported_sanitizers( "x86_64-unknown-illumos" => common_libs("illumos", "x86_64", &["asan"]), "x86_64-pc-solaris" => common_libs("solaris", "x86_64", &["asan"]), "x86_64-unknown-linux-gnu" => { - common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) + common_libs("linux", "x86_64", &["asan", "lsan", "msan", "safestack", "tsan"]) } "x86_64-unknown-linux-musl" => { common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md index a82a53248d4..172048704f4 100644 --- a/src/doc/rustc/src/exploit-mitigations.md +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -55,88 +55,18 @@ Table I \ Summary of exploit mitigations supported by the Rust compiler when building programs for the Linux operating system on the AMD64 architecture and equivalent. -<table class="table"> - <tr> - <td><strong>Exploit mitigation</strong> - </td> - <td><strong>Supported and enabled by default</strong> - </td> - <td><strong>Since</strong> - </td> - </tr> - <tr> - <td>Position-independent executable - </td> - <td>Yes - </td> - <td>0.12.0 (2014-10-09) - </td> - </tr> - <tr> - <td>Integer overflow checks - </td> - <td>Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) - </td> - <td>1.1.0 (2015-06-25) - </td> - </tr> - <tr> - <td>Non-executable memory regions - </td> - <td>Yes - </td> - <td>1.8.0 (2016-04-14) - </td> - </tr> - <tr> - <td>Stack clashing protection - </td> - <td>Yes - </td> - <td>1.20.0 (2017-08-31) - </td> - </tr> - <tr> - <td>Read-only relocations and immediate binding - </td> - <td>Yes - </td> - <td>1.21.0 (2017-10-12) - </td> - </tr> - <tr> - <td>Heap corruption protection - </td> - <td>Yes - </td> - <td>1.32.0 (2019-01-17) (via operating system default or specified allocator) - </td> - </tr> - <tr> - <td>Stack smashing protection - </td> - <td>Yes - </td> - <td>Nightly - </td> - </tr> - <tr> - <td>Forward-edge control flow protection - </td> - <td>Yes - </td> - <td>Nightly - </td> - </tr> - <tr> - <td>Backward-edge control flow protection (e.g., shadow and safe stack) - </td> - <td>No - </td> - <td> - </td> - </tr> -</table> + +| Exploit mitigation | Supported and enabled by default | Since | +| - | - | - | +| Position-independent executable | Yes | 0.12.0 (2014-10-09) | +| Integer overflow checks | Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) | 1.1.0 (2015-06-25) | +| Non-executable memory regions | Yes | 1.8.0 (2016-04-14) | +| Stack clashing protection | Yes | 1.20.0 (2017-08-31) | +| Read-only relocations and immediate binding | Yes | 1.21.0 (2017-10-12) | +| Heap corruption protection | Yes | 1.32.0 (2019-01-17) (via operating system default or specified allocator) | +| Stack smashing protection | Yes | Nightly | +| Forward-edge control flow protection | Yes | Nightly | +| Backward-edge control flow protection (e.g., shadow and safe stack) | Yes | Nightly | <small id="fn:1">1\. See <https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec> @@ -513,20 +443,21 @@ Newer processors provide hardware assistance for backward-edge control flow protection, such as ARM Pointer Authentication, and Intel Shadow Stack as part of Intel CET. -The Rust compiler does not support shadow or safe stack. There is work -currently ongoing to add support for the sanitizers[40], which may or may -not include support for safe stack<sup id="fnref:7" role="doc-noteref"><a -href="#fn:7" class="footnote">7</a></sup>. +The Rust compiler supports shadow stack for aarch64 only +<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup> +on nightly Rust compilers [43]-[44]. Safe stack is available on nightly +Rust compilers [45]-[46]. ```text $ readelf -s target/release/hello-rust | grep __safestack_init + 1177: 00000000000057b0 444 FUNC GLOBAL DEFAULT 9 __safestack_init ``` Fig. 16. Checking if LLVM SafeStack is enabled for a given binary. The presence of the `__safestack_init` symbol indicates that LLVM SafeStack -is enabled for a given binary. Conversely, the absence of the +is enabled for a given binary (see Fig. 16). Conversely, the absence of the `__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a -given binary (see Fig. 16). +given binary. <small id="fn:7">7\. The shadow stack implementation for the AMD64 architecture and equivalent in LLVM was removed due to performance and @@ -698,3 +629,15 @@ defaults (unrelated to `READ_IMPLIES_EXEC`). 42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.” GitHub. <https://github.com/rust-lang/rust/pull/84197> + +43. ivanloz. “Add support for LLVM ShadowCallStack. #98208.” GitHub. + <https://github.com/rust-lang/rust/pull/98208>. + +44. “ShadowCallStack.” The Rust Unstable Book. + [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#shadowcallstack](../unstable-book/compiler-flags/sanitizer.html#shadowcallstack). + +45. W. Wiser. “Add support for LLVM SafeStack #112000” GitHub. + <https://github.com/rust-lang/rust/pull/112000> + +46. “SafeStack.” The Rust Unstable Book. + [https://doc.rust-lang/org/unstable-book/compiler-flags/sanitizer.html#safestack](../unstable-book/compiler-flags/sanitizer.html#safestack). diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index aa776daf09d..49389b28c8f 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -21,7 +21,8 @@ This feature allows for use of one of following sanitizers: * [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads. * [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on Armv8.5-A Memory Tagging Extension. -* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow protection. +* [SafeStack](#safestack) provides backward-edge control flow protection by separating the stack into safe and unsafe regions. +* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow protection (aarch64 only). * [ThreadSanitizer](#threadsanitizer) a fast data race detector. To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`, @@ -712,6 +713,16 @@ To enable this target feature compile with `-C target-feature="+mte"`. See the [LLVM MemTagSanitizer documentation][llvm-memtag] for more details. +# SafeStack + +SafeStack provides backward edge control flow protection by separating the stack into data which is only accessed safely (the safe stack) and all other data (the unsafe stack). + +SafeStack can be enabled with the `-Zsanitizer=safestack` option and is supported on the following targets: + +* `x86_64-unknown-linux-gnu` + +See the [Clang SafeStack documentation][clang-safestack] for more details. + # 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. @@ -828,6 +839,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT [clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html +[clang-safestack]: https://clang.llvm.org/docs/SafeStack.html [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html [linux-kasan]: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 4a57c61406c..18b3b913a68 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -71,6 +71,11 @@ pub(super) fn handle_needs( ignore_reason: "ignored on targets without shadow call stacks", }, Need { + name: "needs-sanitizer-safestack", + condition: cache.sanitizer_safestack, + ignore_reason: "ignored on targets without SafeStack support", + }, + Need { name: "needs-run-enabled", condition: config.run_enabled(), ignore_reason: "ignored when running the resulting test binaries is disabled", @@ -184,6 +189,7 @@ pub(super) struct CachedNeedsConditions { sanitizer_hwaddress: bool, sanitizer_memtag: bool, sanitizer_shadow_call_stack: bool, + sanitizer_safestack: bool, xray: bool, rust_lld: bool, i686_dlltool: bool, @@ -220,6 +226,7 @@ impl CachedNeedsConditions { sanitizer_hwaddress: util::HWASAN_SUPPORTED_TARGETS.contains(target), sanitizer_memtag: util::MEMTAG_SUPPORTED_TARGETS.contains(target), sanitizer_shadow_call_stack: util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(target), + sanitizer_safestack: util::SAFESTACK_SUPPORTED_TARGETS.contains(target), xray: util::XRAY_SUPPORTED_TARGETS.contains(target), // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 748240cc94b..17bed38b65e 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -104,6 +104,8 @@ pub const XRAY_SUPPORTED_TARGETS: &[&str] = &[ "x86_64-unknown-openbsd", ]; +pub const SAFESTACK_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; + pub fn make_new_path(path: &str) -> String { assert!(cfg!(windows)); // Windows just uses PATH as the library search path, so we have to |
