diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 42ba40692b75c..cc82a4c9e8e74 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -6,6 +6,7 @@ use smallvec::{SmallVec, smallvec}; fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); + target_features::sls_features_by_flags(sess, features); // FIXME: LLVM also sets +reserve-x18 here under some conditions. } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 0fb987bdf82ed..d120951382784 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -633,6 +633,7 @@ pub(crate) fn target_cpu(sess: &Session) -> &str { /// The target features for compiler flags other than `-Ctarget-features`. fn llvm_features_by_flags(sess: &Session, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); + target_features::sls_features_by_flags(sess, features); // -Zfixed-x18 if sess.opts.unstable_opts.fixed_x18 { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 53df99993f06b..4dec403306d6f 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -7,6 +7,7 @@ use rustc_middle::middle::codegen_fn_attrs::TargetFeature; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::Session; +use rustc_session::config::HardenSls; use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; @@ -400,6 +401,18 @@ pub fn retpoline_features_by_flags(sess: &Session, features: &mut Vec) { } } +pub fn sls_features_by_flags(sess: &Session, features: &mut Vec) { + match &sess.opts.unstable_opts.harden_sls { + HardenSls::None => (), + HardenSls::All => { + features.push("+harden-sls-ijmp".into()); + features.push("+harden-sls-ret".into()); + } + HardenSls::Return => features.push("+harden-sls-ret".into()), + HardenSls::IndirectJmp => features.push("+harden-sls-ijmp".into()), + } +} + pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { rust_target_features: |tcx, cnum| { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index a91e2140fd44e..3d79c2a97496f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3172,11 +3172,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; @@ -3278,6 +3278,7 @@ pub(crate) mod dep_tracking { Polonius, InliningThreshold, FunctionReturn, + HardenSls, Align, ); @@ -3532,6 +3533,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 626262c844257..0bbc2291d6522 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -808,6 +808,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 = "`spec`"; pub(crate) const parse_mir_include_spans: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)"; @@ -1917,6 +1918,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 (), v: Option<&str>) -> bool { v == Some("spec") } @@ -2254,6 +2266,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"), hint_mostly_unused: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b2af99228fe6d..fdf35bd001ccd 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -433,6 +433,16 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("fma", Stable, &["avx"]), ("fxsr", Stable, &[]), ("gfni", Stable, &["sse2"]), + ( + "harden-sls-ijmp", + Stability::Forbidden { reason: "use `harden-sls` compiler flag instead" }, + &[], + ), + ( + "harden-sls-ret", + Stability::Forbidden { reason: "use `harden-sls` compiler flag instead" }, + &[], + ), ("kl", Stable, &["sse2"]), ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), ("lzcnt", Stable, &[]), diff --git a/tests/codegen/harden-sls.rs b/tests/codegen/harden-sls.rs new file mode 100644 index 0000000000000..76ca2ab702af5 --- /dev/null +++ b/tests/codegen/harden-sls.rs @@ -0,0 +1,35 @@ +// ignore-tidy-linelength +// 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. + +//@ add-core-stubs +//@ 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)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[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..71a23f8fc6af8 --- /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` compiler 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` compiler 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..d8f855317323f --- /dev/null +++ b/tests/ui/target-feature/harden-sls-target-feature-flag.rs @@ -0,0 +1,15 @@ +//@ add-core-stubs +//@ 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] + +//[by_feature]~? WARN target feature `harden-sls-ijmp` cannot be enabled with `-Ctarget-feature`: use `harden-sls` compiler flag instead +//[by_feature]~? WARN target feature `harden-sls-ret` cannot be enabled with `-Ctarget-feature`: use `harden-sls` compiler flag instead