Skip to content

Commit ffce3cd

Browse files
committed
Update exploit mitigations documentation
Updates the rustc book with most up to date information about exploit mitigations supported by the Rust compiler.
1 parent 40a83be commit ffce3cd

File tree

4 files changed

+46
-48
lines changed

4 files changed

+46
-48
lines changed

src/doc/rustc/src/exploit-mitigations.md

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -199,30 +199,33 @@ when attempting to read from the guard page/region. This is also referred to as
199199
The Rust compiler supports stack clashing protection via stack probing, and
200200
enables it by default since version 1.20.0 (2017-08-31)[26][29].
201201

202-
![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.")
203-
Fig. 6. IDA Pro listing cross references to `__rust_probestack` in hello-rust.
204-
205202
```rust
206-
fn hello() {
207-
println!("Hello, world!");
203+
fn main() {
204+
let v: [u8; 16384] = [1; 16384];
205+
let first = &v[0];
206+
println!("The first element is: {first}");
208207
}
208+
```
209+
Fig. 6. hello-rust-stack-probe-1 program.
209210

211+
![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.")
212+
Fig. 7. The "unrolled loop" stack probe variant in modified hello-rust.
213+
214+
```rust
210215
fn main() {
211-
let _: [u64; 1024] = [0; 1024];
212-
hello();
216+
let v: [u8; 65536] = [1; 65536];
217+
let first = &v[0];
218+
println!("The first element is: {first}");
213219
}
214220
```
215-
Fig 7. Modified hello-rust.
221+
Fig. 8. hello-rust-stack-probe-2 program.
216222

217-
![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.")
218-
Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified
219-
hello-rust.
223+
![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.")
224+
Fig. 9. The "standard loop" stack probe variant in modified hello-rust.
220225

221-
To check if stack clashing protection is enabled for a given binary, search for
222-
cross references to `__rust_probestack`. The `__rust_probestack` is called in
223-
the prologue of functions whose stack size is larger than a page size (see Fig.
224-
6), and can be forced for illustration purposes by modifying the hello-rust
225-
example as seen in Fig. 7 and Fig. 8.
226+
To check if stack clashing protection is enabled for a given binary, look for
227+
any of the two stack probe variants in the prologue of functions whose stack
228+
size is larger than a page size (see Figs. 6-9).
226229

227230

228231
### Read-only relocations and immediate binding
@@ -350,15 +353,13 @@ instruction pointer, and checking if this value has changed when returning from
350353
a function. This is also known as “Stack Protector” or “Stack Smashing
351354
Protector (SSP)”.
352355

353-
The Rust compiler supports stack smashing protection on nightly builds[42].
356+
The Rust compiler supports stack smashing protection on nightly builds[40].
354357

355358
![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.")
356359
Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in hello-rust.
357360

358361
To check if stack smashing protection is enabled for a given binary, search for
359-
cross references to `__stack_chk_fail`. The presence of these cross-references
360-
in Rust-compiled code (e.g., `hello_rust::main`) indicates that the stack
361-
smashing protection is enabled (see Fig. 14).
362+
cross references to `__stack_chk_fail` (see Fig. 14).
362363

363364

364365
### Forward-edge control flow protection
@@ -380,17 +381,14 @@ commercially available [grsecurity/PaX Reuse Attack Protector
380381
(RAP)](https://grsecurity.net/rap_faq).
381382

382383
The Rust compiler supports forward-edge control flow protection on nightly
383-
builds[40]-[41] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6"
384+
builds[41]-[42] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6"
384385
class="footnote">6</a></sup>.
385386

386387
```text
387-
$ readelf -s -W target/debug/rust-cfi | grep "\.cfi"
388-
12: 0000000000005170 46 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_one.cfi
389-
15: 00000000000051a0 16 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_two.cfi
390-
17: 0000000000005270 396 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi4main.cfi
391-
...
388+
$ readelf -s -W target/release/hello-rust | grep "\.cfi"
389+
5: 0000000000006480 657 FUNC LOCAL DEFAULT 15 _ZN10hello_rust4main17h4e359f1dcd627c83E.cfi
392390
```
393-
Fig. 15. Checking if LLVM CFI is enabled for a given binary[41].
391+
Fig. 15. Checking if LLVM CFI is enabled for a given binary[42].
394392

395393
The presence of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and
396394
references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge
@@ -429,21 +427,21 @@ Newer processors provide hardware assistance for backward-edge control flow
429427
protection, such as ARM Pointer Authentication, and Intel Shadow Stack as part
430428
of Intel CET.
431429

432-
The Rust compiler supports shadow stack for aarch64 only <sup id="fnref:7"
433-
role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup> on nightly Rust
434-
compilers [43]-[44]. Safe stack is available on nightly Rust compilers
435-
[45]-[46].
430+
The Rust compiler supports shadow stack for the AArch64 architecture<sup
431+
id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup>on
432+
nightly builds[43]-[44], and supports safe stack also on nightly
433+
builds[45]-[46].
436434

437435
```text
438436
$ readelf -s target/release/hello-rust | grep __safestack_init
439-
1177: 00000000000057b0 444 FUNC GLOBAL DEFAULT 9 __safestack_init
437+
678: 0000000000008c80 426 FUNC GLOBAL DEFAULT 15 __safestack_init
440438
```
441439
Fig. 16. Checking if LLVM SafeStack is enabled for a given binary.
442440

443441
The presence of the `__safestack_init` symbol indicates that LLVM SafeStack is
444-
enabled for a given binary (see Fig. 16). Conversely, the absence of the
445-
`__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a
446-
given binary.
442+
enabled for a given binary. Conversely, the absence of the `__safestack_init`
443+
symbol indicates that LLVM SafeStack is not enabled for a given binary (see
444+
Fig. 16).
447445

448446
<small id="fn:7">7\. The shadow stack implementation for the AMD64 architecture
449447
and equivalent in LLVM was removed due to performance and security issues. <a
@@ -560,19 +558,19 @@ to `READ_IMPLIES_EXEC`).
560558
25. A. Clark. “Explicitly disable stack execution on linux and bsd #30859.”
561559
GitHub. <https://github.com/rust-lang/rust/pull/30859>.
562560

563-
26. “Replace stack overflow checking with stack probes #16012.” GitHub.
561+
26. Zoxc. “Replace stack overflow checking with stack probes #16012.” GitHub.
564562
<https://github.com/rust-lang/rust/issues/16012>.
565563

566-
27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and
567-
clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub.
568-
<https://github.com/rust-lang/rust/issues/43241>.
569-
570-
28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub.
564+
27. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub.
571565
<https://github.com/rust-lang/rust/pull/42816>.
572566

573-
29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub.
567+
28. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub.
574568
<https://github.com/rust-lang/compiler-builtins/pull/175>.
575569

570+
29. S. Guelton, S. Ledru, J. Stone. “Bringing Stack Clash Protection to Clang /
571+
X86 — the Open Source Way.” The LLVM Project Blog.
572+
<https://blog.llvm.org/posts/2021-01-05-stack-clash-protection/>.
573+
576574
30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by
577575
default #29877.” GitHub. <https://github.com/rust-lang/rust/issues/29877>.
578576

@@ -605,16 +603,16 @@ to `READ_IMPLIES_EXEC`).
605603
39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub.
606604
<https://github.com/rust-lang/rust/pull/55238>.
607605

608-
40. R. de C Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support
606+
40. bbjornse. “Add codegen option for using LLVM stack smash protection #84197.”
607+
GitHub. <https://github.com/rust-lang/rust/pull/84197>
608+
609+
41. R. de C. Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support
609610
for Rust #89653.” GitHub. <https://github.com/rust-lang/rust/issues/89653>.
610611

611-
41. “ControlFlowIntegrity.” The Rust Unstable Book.
612+
42. “ControlFlowIntegrity.” The Rust Unstable Book.
612613
[https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
613614

614-
42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.”
615-
GitHub. <https://github.com/rust-lang/rust/pull/84197>
616-
617-
43. ivanloz. “Add support for LLVM ShadowCallStack. #98208.” GitHub.
615+
43. I. Lozano. “Add support for LLVM ShadowCallStack #98208.” GitHub.
618616
<https://github.com/rust-lang/rust/pull/98208>.
619617

620618
44. “ShadowCallStack.” The Rust Unstable Book.

src/doc/rustc/src/images/image1.png

146 KB
Loading

src/doc/rustc/src/images/image2.png

124 KB
Loading

src/doc/rustc/src/images/image3.png

867 Bytes
Loading

0 commit comments

Comments
 (0)