about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRamon de C Valle <rcvalle@users.noreply.github.com>2022-03-31 22:51:37 -0700
committerRamon de C Valle <rcvalle@users.noreply.github.com>2022-07-23 10:51:37 -0700
commitf792f26a384cb036199ad30a57a2be22a9feef47 (patch)
treecba59a0aa69edf29367127ca5f8c26aa4239beb8
parent5ad7a646a5df1c7e37fc4529f0f1000091ac902d (diff)
downloadrust-f792f26a384cb036199ad30a57a2be22a9feef47.tar.gz
rust-f792f26a384cb036199ad30a57a2be22a9feef47.zip
Update documentation for LLVM CFI support
This commit updates the documentation for the LLVM Control Flow
Integrity (CFI) support in the Rust compiler (see #95548 and #89653).
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md114
1 files changed, 85 insertions, 29 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..448c0a4a3d2 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -191,7 +191,8 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
 
 The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially
 provides forward-edge control flow protection for Rust-compiled code only by
-aggregating function pointers in groups identified by their number of arguments.
+aggregating function pointers in groups identified by their return and parameter
+types.
 
 Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
 binaries" (i.e., for when C or C++ and Rust -compiled code share the same
@@ -243,7 +244,7 @@ fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
 fn main() {
     let answer = do_twice(add_one, 5);
 
-    println!("The answer is: {answer}");
+    println!("The answer is: {}", answer);
 
     println!("With CFI enabled, you should not see the next answer");
     let f: fn(i32) -> i32 = unsafe {
@@ -253,18 +254,18 @@ fn main() {
     };
     let next_answer = do_twice(f, 5);
 
-    println!("The next answer is: {next_answer}");
+    println!("The next answer is: {}", next_answer);
 }
 ```
 Fig. 1. Modified example from the [Advanced Functions and
 Closures][rust-book-ch19-05] chapter of the [The Rust Programming
 Language][rust-book] book.
 
-[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
-
 ```shell
-$ rustc rust_cfi.rs -o rust_cfi
-$ ./rust_cfi
+$ cargo run --release
+   Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
+    Finished release [optimized] target(s) in 0.76s
+     Running `target/release/rust-cfi-1`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 The next answer is: 14
@@ -272,11 +273,11 @@ $
 ```
 Fig. 2. Build and execution of the modified example with LLVM CFI disabled.
 
-[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
-
 ```shell
-$ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi
-$ ./rust_cfi
+$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+   Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
+    Finished release [optimized] target(s) in 3.39s
+     Running `target/release/rust-cfi-1`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 Illegal instruction
@@ -306,25 +307,25 @@ fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
 fn main() {
     let answer = do_twice(add_one, 5);
 
-    println!("The answer is: {answer}");
+    println!("The answer is: {}", answer);
 
     println!("With CFI enabled, you should not see the next answer");
     let f: fn(i32) -> i32 =
         unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) };
     let next_answer = do_twice(f, 5);
 
-    println!("The next answer is: {next_answer}");
+    println!("The next answer is: {}", next_answer);
 }
 ```
 Fig. 4. Another modified example from the [Advanced Functions and
 Closures][rust-book-ch19-05] chapter of the [The Rust Programming
 Language][rust-book] book.
 
-[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
-
 ```shell
-$ rustc rust_cfi.rs -o rust_cfi
-$ ./rust_cfi
+$ cargo run --release
+   Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
+    Finished release [optimized] target(s) in 0.76s
+     Running `target/release/rust-cfi-2`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 The next answer is: 14
@@ -332,11 +333,11 @@ $
 ```
 Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
 
-[//]: # (FIXME: Replace with output from cargo using nightly when #89652 is merged)
-
 ```shell
-$ rustc -Clto -Zsanitizer=cfi rust_cfi.rs -o rust_cfi
-$ ./rust_cfi
+$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+   Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
+    Finished release [optimized] target(s) in 3.38s
+     Running `target/release/rust-cfi-2`
 The answer is: 12
 With CFI enabled, you should not see the next answer
 Illegal instruction
@@ -346,14 +347,69 @@ Fig. 6. Build and execution of the modified example with LLVM CFI enabled.
 
 When LLVM CFI is enabled, if there are any attempts to change/hijack control
 flow using an indirect branch/call to a function with different number of
-arguments than intended/passed in the call/branch site, the execution is also
-terminated (see Fig. 6).
-
-Forward-edge control flow protection not only by aggregating function pointers
-in groups identified by their number of arguments, but also their argument
-types, will also be provided in later work by defining and using compatible type
-identifiers (see Type metadata in the design document in the tracking
-issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
+parameters than arguments intended/passed in the call/branch site, the
+execution is also terminated (see Fig. 6).
+
+```rust
+use std::mem;
+
+fn add_one(x: i32) -> i32 {
+    x + 1
+}
+
+fn add_two(x: i64) -> i64 {
+    x + 2
+}
+
+fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
+    f(arg) + f(arg)
+}
+
+fn main() {
+    let answer = do_twice(add_one, 5);
+
+    println!("The answer is: {}", answer);
+
+    println!("With CFI enabled, you should not see the next answer");
+    let f: fn(i32) -> i32 =
+        unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) };
+    let next_answer = do_twice(f, 5);
+
+    println!("The next answer is: {}", next_answer);
+}
+```
+Fig. 7. Another modified example from the [Advanced Functions and
+Closures][rust-book-ch19-05] chapter of the [The Rust Programming
+Language][rust-book] book.
+
+```shell
+ cargo run --release
+   Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
+    Finished release [optimized] target(s) in 0.74s
+     Running `target/release/rust-cfi-3`
+The answer is: 12
+With CFI enabled, you should not see the next answer
+The next answer is: 14
+$
+```
+Fig. 8. Build and execution of the modified example with LLVM CFI disabled.
+
+```shell
+$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+   Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
+    Finished release [optimized] target(s) in 3.40s
+     Running `target/release/rust-cfi-3`
+The answer is: 12
+With CFI enabled, you should not see the next answer
+Illegal instruction
+$
+```
+Fig. 9. Build and execution of the modified example with LLVM CFI enabled.
+
+When LLVM CFI is enabled, if there are any attempts to change/hijack control
+flow using an indirect branch/call to a function with different return and
+parameter types than the return type expected and arguments intended/passed in
+the call/branch site, the execution is also terminated (see Fig. 9).
 
 [rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
 [rust-book]: https://doc.rust-lang.org/book/title-page.html