Skip to content

Commit c8c2b2b

Browse files
authored
Rollup merge of rust-lang#68824 - ajpaverd:cfguard-rustbuild, r=Mark-Simulacrum
Enable Control Flow Guard in rustbuild Now that Rust supports Control Flow Guard (rust-lang#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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 14 additions & 0 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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")
Lines changed: 34 additions & 0 deletions
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)