From 821c2d7983d50afce6b9ebef8e7d291d049cdcfd Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Sun, 2 Feb 2025 20:25:00 +0700 Subject: [PATCH] -Zharden-sls flag (target modifier) added to enable mitigation against straight line speculation (SLS) --- compiler/rustc_session/src/config.rs | 21 +++++++++--- compiler/rustc_session/src/options.rs | 27 +++++++++++++++ compiler/rustc_target/src/target_features.rs | 16 +++++++++ tests/codegen/harden-sls.rs | 33 +++++++++++++++++++ ...-sls-target-feature-flag.by_feature.stderr | 12 +++++++ .../harden-sls-target-feature-flag.rs | 14 ++++++++ 6 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 tests/codegen/harden-sls.rs create mode 100644 tests/ui/target-feature/harden-sls-target-feature-flag.by_feature.stderr create mode 100644 tests/ui/target-feature/harden-sls-target-feature-flag.rs diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 8e540b76171f4..1d1fe6a4cf4d9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2944,11 +2944,11 @@ pub(crate) mod dep_tracking { use super::{ AutoDiff, BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn, - InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, - LtoCli, MirStripDebugInfo, NextSolverConfig, OomStrategy, OptLevel, OutFileName, - OutputType, OutputTypes, PatchableFunctionEntry, Polonius, RemapPathScopeComponents, - ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, - SymbolManglingVersion, WasiExecModel, + HardenSls, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, + LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, OomStrategy, OptLevel, + OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, + RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, + SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3049,6 +3049,7 @@ pub(crate) mod dep_tracking { Polonius, InliningThreshold, FunctionReturn, + HardenSls, WasmCAbi, Align, ); @@ -3304,6 +3305,16 @@ pub enum FunctionReturn { ThunkExtern, } +/// The different settings that the `-Zharden-sls` flag can have. +#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)] +pub enum HardenSls { + #[default] + None, + All, + Return, + IndirectJmp, +} + /// Whether extra span comments are included when dumping MIR, via the `-Z mir-include-spans` flag. /// By default, only enabled in the NLL MIR dumps, and disabled in all other passes. #[derive(Clone, Copy, Default, PartialEq, Debug)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 62427bff03e49..b34f52287a209 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -290,6 +290,7 @@ macro_rules! top_level_options { pub fn target_feature_flag_enabled(&self, flag: &str) -> bool { match flag { "x86-retpoline" => self.unstable_opts.x86_retpoline, + "harden-sls" => !matches!(self.unstable_opts.harden_sls, HardenSls::None), _ => false, } } @@ -307,6 +308,17 @@ macro_rules! top_level_options { +retpoline-indirect-calls" ); } + if let Some(features) = match unstable_opts.harden_sls { + HardenSls::None => None, + HardenSls::All => Some("+harden-sls-ijmp,+harden-sls-ret"), + HardenSls::Return => Some("+harden-sls-ret"), + HardenSls::IndirectJmp => Some("+harden-sls-ijmp"), + } { + if !cg.target_feature.is_empty() { + cg.target_feature.push(','); + } + cg.target_feature.push_str(features); + } } } ); @@ -812,6 +824,7 @@ mod desc { "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number"; pub(crate) const parse_llvm_module_flag: &str = ":::. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)"; pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`"; + pub(crate) const parse_harden_sls: &str = "`none`, `all`, `return` or `indirect-jmp`"; pub(crate) const parse_wasm_c_abi: &str = "`legacy` or `spec`"; pub(crate) const parse_mir_include_spans: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)"; @@ -1908,6 +1921,17 @@ pub mod parse { true } + pub(crate) fn parse_harden_sls(slot: &mut HardenSls, v: Option<&str>) -> bool { + match v { + Some("none") => *slot = HardenSls::None, + Some("all") => *slot = HardenSls::All, + Some("return") => *slot = HardenSls::Return, + Some("indirect-jmp") => *slot = HardenSls::IndirectJmp, + _ => return false, + } + true + } + pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool { match v { Some("spec") => *slot = WasmCAbi::Spec, @@ -2236,6 +2260,9 @@ options! { graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED], "use the given `fontname` in graphviz output; can be overridden by setting \ environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"), + harden_sls: HardenSls = (HardenSls::None, parse_harden_sls, [TRACKED TARGET_MODIFIER], + "flag to mitigate against straight line speculation (SLS) [none|all|return|indirect-jmp] \ + (default: none)"), has_thread_local: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(target_thread_local)` directive"), human_readable_cgu_names: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 4e34af4ada5f9..e454076de0ded 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -421,6 +421,22 @@ const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("fma", Stable, &["avx"]), ("fxsr", Stable, &[]), ("gfni", Unstable(sym::avx512_target_feature), &["sse2"]), + ( + "harden-sls-ijmp", + Stability::EnabledByTargetModifierFlag { + reason: "use `harden-sls` target modifier flag instead", + flag: "harden-sls", + }, + &[], + ), + ( + "harden-sls-ret", + Stability::EnabledByTargetModifierFlag { + reason: "use `harden-sls` target modifier flag instead", + flag: "harden-sls", + }, + &[], + ), ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), ("lzcnt", Stable, &[]), ("movbe", Stable, &[]), diff --git a/tests/codegen/harden-sls.rs b/tests/codegen/harden-sls.rs new file mode 100644 index 0000000000000..65fd9aacfd602 --- /dev/null +++ b/tests/codegen/harden-sls.rs @@ -0,0 +1,33 @@ +// Test that the `harden-sls-ijmp`, `harden-sls-ret` target features is (not) emitted when +// the `harden-sls=[none|all|return|indirect-jmp]` flag is (not) set. + +//@ revisions: none all return indirect_jmp +//@ needs-llvm-components: x86 +//@ compile-flags: --target x86_64-unknown-linux-gnu +//@ [none] compile-flags: -Zharden-sls=none +//@ [all] compile-flags: -Zharden-sls=all +//@ [return] compile-flags: -Zharden-sls=return +//@ [indirect_jmp] compile-flags: -Zharden-sls=indirect-jmp + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[no_mangle] +pub fn foo() { + // CHECK: @foo() unnamed_addr #0 + + // none-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} } + // none-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} } + + // all: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp,+harden-sls-ret{{.*}} } + + // return-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} } + // return: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} } + + // indirect_jmp-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} } + // indirect_jmp: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} } +} diff --git a/tests/ui/target-feature/harden-sls-target-feature-flag.by_feature.stderr b/tests/ui/target-feature/harden-sls-target-feature-flag.by_feature.stderr new file mode 100644 index 0000000000000..68a0ecc686d78 --- /dev/null +++ b/tests/ui/target-feature/harden-sls-target-feature-flag.by_feature.stderr @@ -0,0 +1,12 @@ +warning: target feature `harden-sls-ijmp` cannot be enabled with `-Ctarget-feature`: use `harden-sls` target modifier flag instead + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 + +warning: target feature `harden-sls-ret` cannot be enabled with `-Ctarget-feature`: use `harden-sls` target modifier flag instead + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 + +warning: 2 warnings emitted + diff --git a/tests/ui/target-feature/harden-sls-target-feature-flag.rs b/tests/ui/target-feature/harden-sls-target-feature-flag.rs new file mode 100644 index 0000000000000..54405c46fda07 --- /dev/null +++ b/tests/ui/target-feature/harden-sls-target-feature-flag.rs @@ -0,0 +1,14 @@ +//@ revisions: by_flag by_feature +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ [by_flag]compile-flags: -Zharden-sls=all +//@ [by_feature]compile-flags: -Ctarget-feature=+harden-sls-ijmp,+harden-sls-ret +//@ [by_flag]build-pass +// For now this is just a warning. +//@ [by_feature]build-pass +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +pub trait Sized {}