Skip to content

Commit

Permalink
Enable Control Flow Guard in rustbuild
Browse files Browse the repository at this point in the history
  • Loading branch information
ajpaverd committed Feb 10, 2020
1 parent c58e09f commit 87df124
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 0 deletions.
4 changes: 4 additions & 0 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,10 @@
# Use LLVM libunwind as the implementation for Rust's unwinder.
#llvm-libunwind = false

# Enable Windows Control Flow Guard checks in the standard library.
# This only applies from stage 1 onwards, and only for Windows targets.
#control-flow-guard = false

# =============================================================================
# Options for specific targets
#
Expand Down
14 changes: 14 additions & 0 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,20 @@ impl<'a> Builder<'a> {
);
}

// If Control Flow Guard is enabled, pass the `control_flow_guard=checks` flag to rustc
// when compiling the standard library, since this might be linked into the final outputs
// produced by rustc. Since this mitigation is only available on Windows, only enable it
// for the standard library in case the compiler is run on a non-Windows platform.
// This is not needed for stage 0 artifacts because these will only be used for building
// the stage 1 compiler.
if cfg!(windows)
&& mode == Mode::Std
&& self.config.control_flow_guard
&& compiler.stage >= 1
{
rustflags.arg("-Zcontrol_flow_guard=checks");
}

// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version());

Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ pub struct Config {
pub targets: Vec<Interned<String>>,
pub local_rebuild: bool,
pub jemalloc: bool,
pub control_flow_guard: bool,

// dist misc
pub dist_sign_folder: Option<PathBuf>,
Expand Down Expand Up @@ -332,6 +333,7 @@ struct Rust {
jemalloc: Option<bool>,
test_compare_mode: Option<bool>,
llvm_libunwind: Option<bool>,
control_flow_guard: Option<bool>,
}

/// TOML representation of how each build target is configured.
Expand Down Expand Up @@ -578,6 +580,7 @@ impl Config {
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
set(&mut config.control_flow_guard, rust.control_flow_guard);

if let Some(ref backends) = rust.codegen_backends {
config.rust_codegen_backends =
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def v(*args):
o("lldb", "rust.lldb", "build lldb")
o("missing-tools", "dist.missing-tools", "allow failures when building tools")
o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard")

o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
Expand Down
34 changes: 34 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# `control_flow_guard`

The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793).

------------------------

The `-Zcontrol_flow_guard=checks` compiler flag enables the Windows [Control Flow Guard][cfguard-docs] platform security feature. When enabled, the compiler outputs a list of valid indirect call targets, and inserts runtime checks on all indirect jump instructions to ensure that the destination is in the list of valid call targets.

[cfguard-docs]: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard

For testing purposes, the `-Zcontrol_flow_guard=nochecks` compiler flag can be used to emit only the list of valid call targets, but not the runtime checks.

It is strongly recommended to also enable Control Flow Guard checks in all linked libraries, including the standard library.

To enable Control Flow Guard in the standard library, you can use the [cargo `-Zbuild-std` functionality][build-std] to recompile the standard library with the same configuration options as the main program.

[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std

For example:
```cmd
rustup toolchain install --force nightly
rustup component add rust-src
SET RUSTFLAGS=-Zcontrol_flow_guard=checks
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
```

```PowerShell
rustup toolchain install --force nightly
rustup component add rust-src
$Env:RUSTFLAGS = "-Zcontrol_flow_guard=checks"
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
```

Alternatively, if you are building the standard library from source, you can set `control-flow-guard = true` in the config.toml file.

0 comments on commit 87df124

Please sign in to comment.