Skip to content

Commit c8c2b2b

Browse files
authored
Rollup merge of #68824 - ajpaverd:cfguard-rustbuild, r=Mark-Simulacrum
Enable Control Flow Guard in rustbuild Now that Rust supports Control Flow Guard (#68180), add a config.toml option to build the standard library with CFG enabled. r? @nagisa
2 parents b6024c4 + 87df124 commit c8c2b2b

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
@@ -444,6 +444,10 @@
444444
# Use LLVM libunwind as the implementation for Rust's unwinder.
445445
#llvm-libunwind = false
446446

447+
# Enable Windows Control Flow Guard checks in the standard library.
448+
# This only applies from stage 1 onwards, and only for Windows targets.
449+
#control-flow-guard = false
450+
447451
# =============================================================================
448452
# Options for specific targets
449453
#

src/bootstrap/builder.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,20 @@ impl<'a> Builder<'a> {
11351135
);
11361136
}
11371137

1138+
// If Control Flow Guard is enabled, pass the `control_flow_guard=checks` flag to rustc
1139+
// when compiling the standard library, since this might be linked into the final outputs
1140+
// produced by rustc. Since this mitigation is only available on Windows, only enable it
1141+
// for the standard library in case the compiler is run on a non-Windows platform.
1142+
// This is not needed for stage 0 artifacts because these will only be used for building
1143+
// the stage 1 compiler.
1144+
if cfg!(windows)
1145+
&& mode == Mode::Std
1146+
&& self.config.control_flow_guard
1147+
&& compiler.stage >= 1
1148+
{
1149+
rustflags.arg("-Zcontrol_flow_guard=checks");
1150+
}
1151+
11381152
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
11391153
cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version());
11401154

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>,
@@ -333,6 +334,7 @@ struct Rust {
333334
jemalloc: Option<bool>,
334335
test_compare_mode: Option<bool>,
335336
llvm_libunwind: Option<bool>,
337+
control_flow_guard: Option<bool>,
336338
}
337339

338340
/// TOML representation of how each build target is configured.
@@ -580,6 +582,7 @@ impl Config {
580582
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
581583
config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
582584
set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
585+
set(&mut config.control_flow_guard, rust.control_flow_guard);
583586

584587
if let Some(ref backends) = rust.codegen_backends {
585588
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)