-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #93439 - abrown:cf-protection, r=nagisa
Add support for control-flow protection This change adds a flag for configuring control-flow protection in the LLVM backend. In Clang, this flag is exposed as `-fcf-protection` with options `none|branch|return|full`. This convention is followed for `rustc`, though as a codegen option: `rustc -Z cf-protection=<none|branch|return|full>`. Tracking issue for future work is #93754.
- Loading branch information
Showing
5 changed files
with
141 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# `cf-protection` | ||
|
||
This option enables control-flow enforcement technology (CET) on x86; a more detailed description of | ||
CET is available [here]. Similar to `clang`, this flag takes one of the following values: | ||
|
||
- `none` - Disable CET completely (this is the default). | ||
- `branch` - Enable indirect branch tracking (`IBT`). | ||
- `return` - Enable shadow stack (`SHSTK`). | ||
- `full` - Enable both `branch` and `return`. | ||
|
||
[here]: https://www.intel.com/content/www/us/en/develop/articles/technical-look-control-flow-enforcement-technology.html | ||
|
||
This flag only applies to the LLVM backend: it sets the `cf-protection-branch` and | ||
`cf-protection-return` flags on LLVM modules. Note, however, that all compiled modules linked | ||
together must have the flags set for the compiled output to be CET-enabled. Currently, Rust's | ||
standard library does not ship with CET enabled by default, so you may need to rebuild all standard | ||
modules with a `cargo` command like: | ||
|
||
```sh | ||
$ RUSTFLAGS="-Z cf-protection=full" RUSTC="rustc-custom" cargo +nightly build -Z build-std --target x86_64-unknown-linux-gnu | ||
``` | ||
|
||
### Detection | ||
|
||
An ELF binary is CET-enabled if it has the `IBT` and `SHSTK` tags, e.g.: | ||
|
||
```sh | ||
$ readelf -a target/x86_64-unknown-linux-gnu/debug/example | grep feature: | ||
Properties: x86 feature: IBT, SHSTK | ||
``` | ||
|
||
### Troubleshooting | ||
|
||
To display modules that are not CET enabled, examine the linker errors available when `cet-report` is enabled: | ||
|
||
```sh | ||
$ RUSTC_LOG=rustc_codegen_ssa::back::link=info rustc-custom -v -Z cf-protection=full -C link-arg="-Wl,-z,cet-report=warning" -o example example.rs | ||
... | ||
/usr/bin/ld: /.../build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-d73f7266be14cb8b.rlib(std-d73f7266be14cb8b.std.f7443020-cgu.12.rcgu.o): warning: missing IBT and SHSTK properties | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Test that the correct module flags are emitted with different control-flow protection flags. | ||
|
||
// revisions: undefined none branch return full | ||
// needs-llvm-components: x86 | ||
// [undefined] compile-flags: | ||
// [none] compile-flags: -Z cf-protection=none | ||
// [branch] compile-flags: -Z cf-protection=branch | ||
// [return] compile-flags: -Z cf-protection=return | ||
// [full] compile-flags: -Z cf-protection=full | ||
// compile-flags: --target x86_64-unknown-linux-gnu | ||
|
||
#![crate_type = "lib"] | ||
#![feature(no_core, lang_items)] | ||
#![no_core] | ||
|
||
#[lang="sized"] | ||
trait Sized { } | ||
|
||
// A basic test function. | ||
pub fn test() { | ||
} | ||
|
||
// undefined-NOT: !"cf-protection-branch" | ||
// undefined-NOT: !"cf-protection-return" | ||
|
||
// none-NOT: !"cf-protection-branch" | ||
// none-NOT: !"cf-protection-return" | ||
|
||
// branch-NOT: !"cf-protection-return" | ||
// branch: !"cf-protection-branch", i32 1 | ||
// branch-NOT: !"cf-protection-return" | ||
|
||
// return-NOT: !"cf-protection-branch" | ||
// return: !"cf-protection-return", i32 1 | ||
// return-NOT: !"cf-protection-branch" | ||
|
||
// full: !"cf-protection-branch", i32 1 | ||
// full: !"cf-protection-return", i32 1 |