Skip to content

Commit 87df124

Browse files
committed
Enable Control Flow Guard in rustbuild
1 parent c58e09f commit 87df124

File tree

5 files changed

+56
-0
lines changed

5 files changed

+56
-0
lines changed

config.toml.example

+4
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,10 @@
435435
# Use LLVM libunwind as the implementation for Rust's unwinder.
436436
#llvm-libunwind = false
437437

438+
# Enable Windows Control Flow Guard checks in the standard library.
439+
# This only applies from stage 1 onwards, and only for Windows targets.
440+
#control-flow-guard = false
441+
438442
# =============================================================================
439443
# Options for specific targets
440444
#

src/bootstrap/builder.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,20 @@ impl<'a> Builder<'a> {
11111111
);
11121112
}
11131113

1114+
// If Control Flow Guard is enabled, pass the `control_flow_guard=checks` flag to rustc
1115+
// when compiling the standard library, since this might be linked into the final outputs
1116+
// produced by rustc. Since this mitigation is only available on Windows, only enable it
1117+
// for the standard library in case the compiler is run on a non-Windows platform.
1118+
// This is not needed for stage 0 artifacts because these will only be used for building
1119+
// the stage 1 compiler.
1120+
if cfg!(windows)
1121+
&& mode == Mode::Std
1122+
&& self.config.control_flow_guard
1123+
&& compiler.stage >= 1
1124+
{
1125+
rustflags.arg("-Zcontrol_flow_guard=checks");
1126+
}
1127+
11141128
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
11151129
cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version());
11161130

src/bootstrap/config.rs

+3
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ pub struct Config {
116116
pub targets: Vec<Interned<String>>,
117117
pub local_rebuild: bool,
118118
pub jemalloc: bool,
119+
pub control_flow_guard: bool,
119120

120121
// dist misc
121122
pub dist_sign_folder: Option<PathBuf>,
@@ -332,6 +333,7 @@ struct Rust {
332333
jemalloc: Option<bool>,
333334
test_compare_mode: Option<bool>,
334335
llvm_libunwind: Option<bool>,
336+
control_flow_guard: Option<bool>,
335337
}
336338

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

582585
if let Some(ref backends) = rust.codegen_backends {
583586
config.rust_codegen_backends =

src/bootstrap/configure.py

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def v(*args):
6060
o("lldb", "rust.lldb", "build lldb")
6161
o("missing-tools", "dist.missing-tools", "allow failures when building tools")
6262
o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
63+
o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard")
6364

6465
o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
6566
o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# `control_flow_guard`
2+
3+
The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793).
4+
5+
------------------------
6+
7+
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.
8+
9+
[cfguard-docs]: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard
10+
11+
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.
12+
13+
It is strongly recommended to also enable Control Flow Guard checks in all linked libraries, including the standard library.
14+
15+
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.
16+
17+
[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
18+
19+
For example:
20+
```cmd
21+
rustup toolchain install --force nightly
22+
rustup component add rust-src
23+
SET RUSTFLAGS=-Zcontrol_flow_guard=checks
24+
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
25+
```
26+
27+
```PowerShell
28+
rustup toolchain install --force nightly
29+
rustup component add rust-src
30+
$Env:RUSTFLAGS = "-Zcontrol_flow_guard=checks"
31+
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
32+
```
33+
34+
Alternatively, if you are building the standard library from source, you can set `control-flow-guard = true` in the config.toml file.

0 commit comments

Comments
 (0)