Skip to content

Commit

Permalink
Update documentation for LLVM CFI support
Browse files Browse the repository at this point in the history
This commit updates the documentation for the LLVM Control Flow
Integrity (CFI) support in the Rust compiler (see #95548 and #89653).
  • Loading branch information
rcvalle committed Jul 23, 2022
1 parent 5ad7a64 commit f792f26
Showing 1 changed file with 85 additions and 29 deletions.
114 changes: 85 additions & 29 deletions src/doc/unstable-book/src/compiler-flags/sanitizer.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -253,30 +254,30 @@ 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
$
```
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
Expand Down Expand Up @@ -306,37 +307,37 @@ 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
$
```
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
Expand All @@ -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
Expand Down

0 comments on commit f792f26

Please sign in to comment.