about summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-11-22 09:28:50 -0800
committerGitHub <noreply@github.com>2023-11-22 09:28:50 -0800
commit1fb2624205f4350ee649919d59b907f6773b2537 (patch)
tree2d739b62b509978a75faba9741e4f2b894686562 /src/bootstrap
parentd58ded905835366fa4ddfc60ea5dfb9799c81fb7 (diff)
parent80896cbe351aa31ddc2f805c71e7eff85495d902 (diff)
Rollup merge of #118013 - sivadeilra:user/ardavis/ehcont, r=wesleywiser
Enable Rust to use the EHCont security feature of Windows

In the future Windows will enable Control-flow Enforcement Technology (CET aka Shadow Stacks). To protect the path where the context is updated during exception handling, the binary is required to enumerate valid unwind entrypoints in a dedicated section which is validated when the context is being set during exception handling.

The required support for EHCONT Guard has already been merged into LLVM, long ago. This change simply adds the Rust codegen option to enable it.

Relevant LLVM change: https://reviews.llvm.org/D40223

This also adds a new `ehcont-guard` option to the bootstrap config which enables EHCont Guard when building std.

We at Microsoft have been using this feature for a significant period of time; we are confident that the LLVM feature, when enabled, generates well-formed code.

We currently enable EHCONT using a codegen feature, but I'm certainly open to refactoring this to be a target feature instead, or to use any appropriate mechanism to enable it.
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/src/core/builder.rs10
-rw-r--r--src/bootstrap/src/core/config/config.rs3
-rw-r--r--src/bootstrap/src/tests/builder.rs2
3 files changed, 14 insertions, 1 deletions
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index c755324df1a..507306fd274 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -1964,6 +1964,16 @@ impl<'a> Builder<'a> {
             rustflags.arg("-Ccontrol-flow-guard");
         }
 
+        // If EHCont Guard is enabled, pass the `-Zehcont-guard` 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.ehcont_guard && compiler.stage >= 1 {
+            rustflags.arg("-Zehcont-guard");
+        }
+
         // For `cargo doc` invocations, make rustdoc print the Rust version into the docs
         // This replaces spaces with tabs because RUSTDOCFLAGS does not
         // support arguments with regular spaces. Hopefully someday Cargo will
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index fa8b0b20cec..9ef90798590 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -248,6 +248,7 @@ pub struct Config {
     pub local_rebuild: bool,
     pub jemalloc: bool,
     pub control_flow_guard: bool,
+    pub ehcont_guard: bool,
 
     // dist misc
     pub dist_sign_folder: Option<PathBuf>,
@@ -1019,6 +1020,7 @@ define_config! {
         test_compare_mode: Option<bool> = "test-compare-mode",
         llvm_libunwind: Option<String> = "llvm-libunwind",
         control_flow_guard: Option<bool> = "control-flow-guard",
+        ehcont_guard: Option<bool> = "ehcont-guard",
         new_symbol_mangling: Option<bool> = "new-symbol-mangling",
         profile_generate: Option<String> = "profile-generate",
         profile_use: Option<String> = "profile-use",
@@ -1452,6 +1454,7 @@ impl Config {
             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);
+            set(&mut config.ehcont_guard, rust.ehcont_guard);
             config.llvm_libunwind_default = rust
                 .llvm_libunwind
                 .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
diff --git a/src/bootstrap/src/tests/builder.rs b/src/bootstrap/src/tests/builder.rs
index 96139f7b099..744015e8e82 100644
--- a/src/bootstrap/src/tests/builder.rs
+++ b/src/bootstrap/src/tests/builder.rs
@@ -1,6 +1,6 @@
 use super::*;
-use crate::core::config::{Config, DryRun, TargetSelection};
 use crate::core::build_steps::doc::DocumentationFormat;
+use crate::core::config::{Config, DryRun, TargetSelection};
 use std::thread;
 
 fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {