about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRamon de C Valle <rcvalle@users.noreply.github.com>2023-07-28 16:22:04 -0700
committerRamon de C Valle <rcvalle@users.noreply.github.com>2023-11-08 07:27:57 -0800
commit7c385f5a03c08df98aca71fbe4ef57dff66ffa56 (patch)
tree368150b9cab201549dc2df040ddb4138c816253e
parent40a83be6eb91efffa1965f4480b8c035524d44be (diff)
downloadrust-7c385f5a03c08df98aca71fbe4ef57dff66ffa56.tar.gz
rust-7c385f5a03c08df98aca71fbe4ef57dff66ffa56.zip
Update exploit mitigations documentation
Updates the rustc book with most up to date information about exploit
mitigations supported by the Rust compiler.
-rw-r--r--src/doc/rustc/src/exploit-mitigations.md122
-rw-r--r--src/doc/rustc/src/images/image1.pngbin15293 -> 164896 bytes
-rw-r--r--src/doc/rustc/src/images/image2.pngbin28772 -> 155307 bytes
-rw-r--r--src/doc/rustc/src/images/image3.pngbin19069 -> 19936 bytes
4 files changed, 62 insertions, 60 deletions
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
index f02a4dcf963..d4e2fc52e97 100644
--- a/src/doc/rustc/src/exploit-mitigations.md
+++ b/src/doc/rustc/src/exploit-mitigations.md
@@ -43,7 +43,8 @@ understood within a given context.
 This section documents the exploit mitigations applicable to the Rust compiler
 when building programs for the Linux operating system on the AMD64 architecture
 and equivalent.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1"
-class="footnote">1</a></sup>
+class="footnote">1</a></sup> All examples in this section were built using
+nightly builds of the Rust compiler on Debian testing.
 
 The Rust Programming Language currently has no specification. The Rust compiler
 (i.e., rustc) is the language reference implementation. All references to “the
@@ -102,7 +103,10 @@ and unsigned integer computations that cannot be represented in their type,
 resulting in an overflow or wraparound.
 
 The Rust compiler supports integer overflow checks, and enables it when debug
-assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20].
+assertions are enabled since version 1.0.0 (2015-05-15)[14]–[17], but support
+for it was not completed until version 1.1.0 (2015-06-25)[16]. An option to
+control integer overflow checks was later stabilized in version 1.17.0
+(2017-04-27)[18]–[20].
 
 ```compile_fail
 fn main() {
@@ -120,7 +124,7 @@ $ cargo run
 thread 'main' panicked at 'attempt to add with overflow', src/main.rs:3:23
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 ```
-Fig. 3. Build and execution of hello-rust-integer with debug assertions
+Fig. 3. Build and execution of hello-rust-integer with debug assertions
 enabled.
 
 ```text
@@ -130,7 +134,7 @@ $ cargo run --release
      Running `target/release/hello-rust-integer`
 u: 0
 ```
-Fig. 4. Build and execution of hello-rust-integer with debug assertions
+Fig. 4. Build and execution of hello-rust-integer with debug assertions
 disabled.
 
 Integer overflow checks are enabled when debug assertions are enabled (see Fig.
@@ -156,7 +160,7 @@ Non-executable memory regions increase the difficulty of exploitation by
 limiting the memory regions that can be used to execute arbitrary code. Most
 modern processors provide support for the operating system to mark memory
 regions as non executable, but it was previously emulated by software, such as
-in grsecurity/PaX's [PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt)
+in grsecurity/PaX’s [PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt)
 and [SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors
 that did not provide support for it. This is also known as “No Execute (NX)
 Bit”, “Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others.
@@ -171,7 +175,7 @@ $ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK
   GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                  0x0000000000000000 0x0000000000000000  RW     0x10
 ```
-Fig. 5. Checking if non-executable memory regions are enabled for a given
+Fig. 5. Checking if non-executable memory regions are enabled for a given
 binary.
 
 The presence of an element of type `PT_GNU_STACK` in the program header table
@@ -199,30 +203,33 @@ when attempting to read from the guard page/region. This is also referred to as
 The Rust compiler supports stack clashing protection via stack probing, and
 enables it by default since version 1.20.0 (2017-08-31)[26]–[29].
 
-![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.")
-Fig. 6. IDA Pro listing cross references to `__rust_probestack` in hello-rust.
-
 ```rust
-fn hello() {
-    println!("Hello, world!");
+fn main() {
+    let v: [u8; 16384] = [1; 16384];
+    let first = &v[0];
+    println!("The first element is: {first}");
 }
+```
+Fig. 6. hello-rust-stack-probe-1 program.
 
+![Screenshot of IDA Pro listing the "unrolled loop" stack probe variant in modified hello-rust.](images/image1.png "The \"unrolled loop\" stack probe variant in modified hello-rust.")
+Fig. 7. The "unrolled loop" stack probe variant in modified hello-rust.
+
+```rust
 fn main() {
-    let _: [u64; 1024] = [0; 1024];
-    hello();
+    let v: [u8; 65536] = [1; 65536];
+    let first = &v[0];
+    println!("The first element is: {first}");
 }
 ```
-Fig 7. Modified hello-rust.
+Fig. 8. hello-rust-stack-probe-2 program.
 
-![Screenshot of IDA Pro listing cross references to __rust_probestack in modified hello-rust.](images/image2.png "Cross references to __rust_probestack in modified hello-rust.")
-Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified
-hello-rust.
+![Screenshot of IDA Pro listing the "standard loop" stack probe variant in modified hello-rust.](images/image2.png "The \"standard loop\" stack probe variant in modified hello-rust.")
+Fig. 9. The "standard loop" stack probe variant in modified hello-rust.
 
-To check if stack clashing protection is enabled for a given binary, search for
-cross references to `__rust_probestack`. The `__rust_probestack` is called in
-the prologue of functions whose stack size is larger than a page size (see Fig.
-6), and can be forced for illustration purposes by modifying the hello-rust
-example as seen in Fig. 7 and Fig. 8.
+To check if stack clashing protection is enabled for a given binary, look for
+any of the two stack probe variants in the prologue of functions whose stack
+size is larger than a page size (see Figs. 6–9).
 
 
 ### Read-only relocations and immediate binding
@@ -272,7 +279,7 @@ section indicates immediate binding is not enabled for a given binary.
 The presence of both an element of type `PT_GNU_RELRO` in the program header
 table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag
 in the dynamic section indicates full RELRO is enabled for a given binary (see
-Fig. 9 and Fig. 10).
+Figs. 9–10).
 
 <small id="fn:4">4\. And the `DF_1_NOW` flag for some link editors. <a
 href="#fnref:4" class="reversefootnote" role="doc-backlink">↩</a></small>
@@ -321,7 +328,7 @@ $ cargo run
 free(): invalid next size (normal)
 Aborted
 ```
-Fig. 12. Build and execution of hello-rust-heap with debug assertions enabled.
+Fig. 12. Build and execution of hello-rust-heap with debug assertions enabled.
 
 ```text
 $ cargo run --release
@@ -331,10 +338,10 @@ $ cargo run --release
 free(): invalid next size (normal)
 Aborted
 ```
-Fig. 13. Build and execution of hello-rust-heap with debug assertions disabled.
+Fig. 13. Build and execution of hello-rust-heap with debug assertions disabled.
 
-Heap corruption checks are being performed when using the default allocator
-(i.e., the GNU Allocator) as seen in Fig. 12 and Fig. 13.
+Heap corruption checks are performed when using the default allocator (i.e.,
+the GNU Allocator) (see Figs. 12–13).
 
 <small id="fn:5">5\. Linux's standard C library default allocator is the GNU
 Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram Gloger,
@@ -350,15 +357,13 @@ instruction pointer, and checking if this value has changed when returning from
 a function. This is also known as “Stack Protector” or “Stack Smashing
 Protector (SSP)”.
 
-The Rust compiler supports stack smashing protection on nightly builds[42].
+The Rust compiler supports stack smashing protection on nightly builds[40].
 
 ![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.")
 Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in hello-rust.
 
 To check if stack smashing protection is enabled for a given binary, search for
-cross references to `__stack_chk_fail`. The presence of these cross-references
-in Rust-compiled code (e.g., `hello_rust::main`) indicates that the stack
-smashing protection is enabled (see Fig. 14).
+cross references to `__stack_chk_fail` (see Fig. 14).
 
 
 ### Forward-edge control flow protection
@@ -380,17 +385,14 @@ commercially available [grsecurity/PaX Reuse Attack Protector
 (RAP)](https://grsecurity.net/rap_faq).
 
 The Rust compiler supports forward-edge control flow protection on nightly
-builds[40]-[41] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6"
+builds[41]-[42] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6"
 class="footnote">6</a></sup>.
 
 ```text
-$ readelf -s -W target/debug/rust-cfi | grep "\.cfi"
-    12: 0000000000005170    46 FUNC    LOCAL  DEFAULT   14 _RNvCsjaOHoaNjor6_8rust_cfi7add_one.cfi
-    15: 00000000000051a0    16 FUNC    LOCAL  DEFAULT   14 _RNvCsjaOHoaNjor6_8rust_cfi7add_two.cfi
-    17: 0000000000005270   396 FUNC    LOCAL  DEFAULT   14 _RNvCsjaOHoaNjor6_8rust_cfi4main.cfi
-...
+$ readelf -s -W target/release/hello-rust | grep "\.cfi"
+     5: 0000000000006480   657 FUNC    LOCAL  DEFAULT   15 _ZN10hello_rust4main17h4e359f1dcd627c83E.cfi
 ```
-Fig. 15. Checking if LLVM CFI is enabled for a given binary[41].
+Fig. 15. Checking if LLVM CFI is enabled for a given binary.
 
 The presence of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and
 references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge
@@ -429,21 +431,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 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].
+The Rust compiler supports shadow stack for the AArch64 architecture<sup
+id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup>on
+nightly builds[43]-[44], and also supports safe stack on nightly
+builds[45]-[46].
 
 ```text
 $ readelf -s target/release/hello-rust | grep __safestack_init
-  1177: 00000000000057b0   444 FUNC    GLOBAL DEFAULT    9 __safestack_init
+   678: 0000000000008c80   426 FUNC    GLOBAL DEFAULT   15 __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 (see Fig. 16). Conversely, the absence of the
-`__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a
-given binary.
+enabled for a given binary. Conversely, the absence of the `__safestack_init`
+symbol indicates that LLVM SafeStack is not enabled for a given binary (see
+Fig. 16).
 
 <small id="fn:7">7\. The shadow stack implementation for the AMD64 architecture
 and equivalent in LLVM was removed due to performance and security issues. <a
@@ -458,7 +460,7 @@ the `PT_GNU_STACK` program header indicates whether the stack should be
 executable, and the absence of this header indicates that the stack should be
 executable. However, the Linux kernel currently sets the `READ_IMPLIES_EXEC`
 personality upon loading any executable with the `PT_GNU_STACK` program header
-and the `PF_X `flag set or with the absence of this header, resulting in not
+and the `PF_X` flag set or with the absence of this header, resulting in not
 only the stack, but also all readable virtual memory mappings being executable.
 
 An attempt to fix this [was made in
@@ -560,19 +562,19 @@ to `READ_IMPLIES_EXEC`).
 25. A. Clark. “Explicitly disable stack execution on linux and bsd #30859.”
     GitHub. <https://github.com/rust-lang/rust/pull/30859>.
 
-26. “Replace stack overflow checking with stack probes #16012.” GitHub.
+26. Zoxc. “Replace stack overflow checking with stack probes #16012.” GitHub.
     <https://github.com/rust-lang/rust/issues/16012>.
 
-27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and
-    clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub.
-    <https://github.com/rust-lang/rust/issues/43241>.
-
-28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub.
+27. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub.
     <https://github.com/rust-lang/rust/pull/42816>.
 
-29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub.
+28. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub.
     <https://github.com/rust-lang/compiler-builtins/pull/175>.
 
+29. S. Guelton, S. Ledru, J. Stone. “Bringing Stack Clash Protection to Clang /
+    X86 — the Open Source Way.” The LLVM Project Blog.
+    <https://blog.llvm.org/posts/2021-01-05-stack-clash-protection/>.
+
 30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by
     default #29877.” GitHub. <https://github.com/rust-lang/rust/issues/29877>.
 
@@ -605,16 +607,16 @@ to `READ_IMPLIES_EXEC`).
 39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub.
     <https://github.com/rust-lang/rust/pull/55238>.
 
-40. R. de C Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support
+40. bbjornse. “Add codegen option for using LLVM stack smash protection #84197.”
+    GitHub. <https://github.com/rust-lang/rust/pull/84197>
+
+41. R. de C. Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support
     for Rust #89653.” GitHub. <https://github.com/rust-lang/rust/issues/89653>.
 
-41. “ControlFlowIntegrity.” The Rust Unstable Book.
+42. “ControlFlowIntegrity.” The Rust Unstable Book.
     [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
 
-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.
+43. I. Lozano. “Add support for LLVM ShadowCallStack #98208.” GitHub.
     <https://github.com/rust-lang/rust/pull/98208>.
 
 44. “ShadowCallStack.” The Rust Unstable Book.
diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png
index ee2d3fd4f43..0da45e56620 100644
--- a/src/doc/rustc/src/images/image1.png
+++ b/src/doc/rustc/src/images/image1.png
Binary files differdiff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png
index 03061e1f0b1..a9cf23f8737 100644
--- a/src/doc/rustc/src/images/image2.png
+++ b/src/doc/rustc/src/images/image2.png
Binary files differdiff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png
index ef02c605ead..844a2fe6747 100644
--- a/src/doc/rustc/src/images/image3.png
+++ b/src/doc/rustc/src/images/image3.png
Binary files differ