1
Fork 0

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).
This commit is contained in:
Ramon de C Valle 2022-03-31 22:51:37 -07:00
parent 5ad7a646a5
commit f792f26a38

View file

@ -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).
parameters than arguments 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)).
```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