Skip to content

Commit 9a02f65

Browse files
committed
Update documentation for LLVM CFI support
This commit updates the documentation for the LLVM Control Flow Integrity (CFI) support in the Rust compiler.
1 parent 004aa15 commit 9a02f65

File tree

2 files changed

+126
-17
lines changed

2 files changed

+126
-17
lines changed

src/doc/unstable-book/src/compiler-flags/sanitizer.md

+101-17
Original file line numberDiff line numberDiff line change
@@ -196,18 +196,18 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
196196
197197
# ControlFlowIntegrity
198198
199-
The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially
200-
provides forward-edge control flow protection for Rust-compiled code only by
201-
aggregating function pointers in groups identified by their return and parameter
202-
types.
203-
204-
Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
205-
binaries" (i.e., for when C or C++ and Rust -compiled code share the same
206-
virtual address space) will be provided in later work by defining and using
207-
compatible type identifiers (see Type metadata in the design document in the
208-
tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
209-
210-
LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto).
199+
The LLVM Control Flow Integrity (CFI) support in the Rust compiler provides
200+
forward-edge control flow protection for both Rust-compiled code only and for C
201+
or C++ and Rust -compiled code mixed-language binaries, also known as “mixed
202+
binaries” (i.e., for when C or C++ and Rust -compiled code share the same
203+
virtual address space), by aggregating function pointers in groups identified by
204+
their return and parameter types.
205+
206+
LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., `-Clto`).
207+
Cross-language LLVM CFI can be enabled with `-Zsanitizer=cfi`, and requires the
208+
`-Zsanitizer-cfi-normalize-integers` option to be used with Clang
209+
`-fsanitize-cfi-icall-normalize-integers` for normalizing integer types, and
210+
proper (i.e., non-rustc) LTO (i.e., `-Clinker-plugin-lto`).
211211
212212
See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details.
213213
@@ -343,7 +343,7 @@ $
343343
Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
344344
345345
```shell
346-
$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
346+
$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
347347
Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
348348
Finished release [optimized] target(s) in 3.38s
349349
Running `target/release/rust-cfi-2`
@@ -392,7 +392,7 @@ Closures][rust-book-ch19-05] chapter of the [The Rust Programming
392392
Language][rust-book] book.
393393
394394
```shell
395-
cargo run --release
395+
$ cargo run --release
396396
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
397397
Finished release [optimized] target(s) in 0.74s
398398
Running `target/release/rust-cfi-3`
@@ -404,7 +404,7 @@ $
404404
Fig. 8. Build and execution of the modified example with LLVM CFI disabled.
405405
406406
```shell
407-
$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
407+
$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
408408
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
409409
Finished release [optimized] target(s) in 3.40s
410410
Running `target/release/rust-cfi-3`
@@ -420,8 +420,92 @@ flow using an indirect branch/call to a function with different return and
420420
parameter types than the return type expected and arguments intended/passed in
421421
the call/branch site, the execution is also terminated (see Fig. 9).
422422
423-
[rust-book-ch19-05]: ../../book/ch19-05-advanced-functions-and-closures.html
424-
[rust-book]: ../../book/title-page.html
423+
```ignore (cannot-test-this-because-uses-custom-build)
424+
int
425+
do_twice(int (*fn)(int), int arg) {
426+
return fn(arg) + fn(arg);
427+
}
428+
```
429+
Fig. 10. Example C library.
430+
431+
```ignore (cannot-test-this-because-uses-custom-build)
432+
use std::mem;
433+
434+
#[link(name = "foo")]
435+
extern "C" {
436+
fn do_twice(f: unsafe extern "C" fn(i32) -> i32, arg: i32) -> i32;
437+
}
438+
439+
unsafe extern "C" fn add_one(x: i32) -> i32 {
440+
x + 1
441+
}
442+
443+
unsafe extern "C" fn add_two(x: i64) -> i64 {
444+
x + 2
445+
}
446+
447+
fn main() {
448+
let answer = unsafe { do_twice(add_one, 5) };
449+
450+
println!("The answer is: {}", answer);
451+
452+
println!("With CFI enabled, you should not see the next answer");
453+
let f: unsafe extern "C" fn(i32) -> i32 = unsafe {
454+
mem::transmute::<*const u8, unsafe extern "C" fn(i32) -> i32>(add_two as *const u8)
455+
};
456+
let next_answer = unsafe { do_twice(f, 5) };
457+
458+
println!("The next answer is: {}", next_answer);
459+
}
460+
```
461+
Fig. 11. Another modified example from the [Advanced Functions and
462+
Closures][rust-book-ch19-05] chapter of the [The Rust Programming
463+
Language][rust-book] book.
464+
465+
```shell
466+
$ make
467+
mkdir -p target/debug
468+
clang -I. -Isrc -Wall -flto -fvisibility=hidden -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
469+
llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
470+
RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build
471+
Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
472+
Finished dev [unoptimized + debuginfo] target(s) in 0.45s
473+
$ ./target/debug/main
474+
The answer is: 12
475+
With CFI enabled, you should not see the next answer
476+
The next answer is: 14
477+
$
478+
```
479+
Fig. 12. Build and execution of the modified example with LLVM CFI disabled.
480+
481+
```shell
482+
$ make
483+
mkdir -p target/debug
484+
clang -I. -Isrc -Wall -flto -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-icall-normalize-integers -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
485+
llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
486+
RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build
487+
Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
488+
Finished dev [unoptimized + debuginfo] target(s) in 0.45s
489+
$ ./target/debug/main
490+
The answer is: 12
491+
With CFI enabled, you should not see the next answer
492+
Illegal instruction
493+
$
494+
```
495+
Fig. 13. Build and execution of the modified example with LLVM CFI enabled.
496+
497+
When LLVM CFI is enabled, if there are any attempts to change/hijack control
498+
flow using an indirect branch/call to a function with different return and
499+
parameter types than the return type expected and arguments intended/passed in
500+
the call/branch site, even across the FFI boundary and for extern "C" function
501+
types indirectly called (i.e., callbacks/function pointers) across the FFI
502+
boundary, in C or C++ and Rust -compiled code mixed-language binaries, also
503+
known as “mixed binaries” (i.e., for when C or C++ and Rust -compiled code share
504+
the same virtual address space), the execution is also terminated (see Fig. 13).
505+
506+
507+
[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
508+
[rust-book]: https://doc.rust-lang.org/book/title-page.html
425509
426510
# HWAddressSanitizer
427511
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# `cfi_encoding`
2+
3+
The tracking issue for this feature is: [#89653]
4+
5+
[#89653]: https://github.com/rust-lang/rust/issues/89653
6+
7+
------------------------
8+
9+
The `cfi_encoding` feature allows the user to define a CFI encoding for a type.
10+
It allows the user to use a different names for types that otherwise would be
11+
required to have the same name as used in externally defined C functions.
12+
13+
## Examples
14+
15+
```rust
16+
#![feature(cfi_encoding, extern_types)]
17+
18+
#[cfi_encoding = "3Foo"]
19+
pub struct Type1(i32);
20+
21+
extern {
22+
#[cfi_encoding = "3Bar"]
23+
type Type2;
24+
}
25+
```

0 commit comments

Comments
 (0)