Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

-Zharden-sls flag (target modifier) added to enable mitigation against straight line speculation (SLS) #136597

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_gcc/src/gcc_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
sess.dcx().emit_warn(unknown_feature);
}
Some(&(_, stability, _)) => {
if let Err(reason) = stability.toggle_allowed() {
if let Err(reason) =
stability.toggle_allowed(|flag| sess.opts.target_feature_flag_enabled(flag))
{
sess.dcx().emit_warn(ForbiddenCTargetFeature {
feature,
enabled: if enable { "enabled" } else { "disabled" },
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,9 @@ pub(crate) fn global_llvm_features(
sess.dcx().emit_warn(unknown_feature);
}
Some((_, stability, _)) => {
if let Err(reason) = stability.toggle_allowed() {
if let Err(reason) = stability
.toggle_allowed(|flag| sess.opts.target_feature_flag_enabled(flag))
{
sess.dcx().emit_warn(ForbiddenCTargetFeature {
feature,
enabled: if enable { "enabled" } else { "disabled" },
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ pub(crate) fn from_target_feature_attr(

// Only allow target features whose feature gates have been enabled
// and which are permitted to be toggled.
if let Err(reason) = stability.toggle_allowed() {
if let Err(reason) =
stability.toggle_allowed(|flag| tcx.sess.opts.target_feature_flag_enabled(flag))
{
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
span: item.span(),
feature,
Expand Down
23 changes: 18 additions & 5 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M

let prints = collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches);

Options::fill_target_features_by_flags(&unstable_opts, &mut cg);

let cg = cg;

let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
Expand Down Expand Up @@ -2942,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;
Expand Down Expand Up @@ -3047,6 +3049,7 @@ pub(crate) mod dep_tracking {
Polonius,
InliningThreshold,
FunctionReturn,
HardenSls,
WasmCAbi,
Align,
);
Expand Down Expand Up @@ -3302,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)]
Expand Down
52 changes: 52 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,40 @@ macro_rules! top_level_options {
mods.sort_by(|a, b| a.opt.cmp(&b.opt));
mods
}

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,
}
}

pub fn fill_target_features_by_flags(
unstable_opts: &UnstableOptions, cg: &mut CodegenOptions
) {
if unstable_opts.x86_retpoline {
if !cg.target_feature.is_empty() {
cg.target_feature.push(',');
}
cg.target_feature.push_str(
"+retpoline-external-thunk,\
+retpoline-indirect-branches,\
+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);
}
}
}
);
}
Expand Down Expand Up @@ -790,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 = "<key>:<type>:<value>:<behavior>. 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`)";
Expand Down Expand Up @@ -1886,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,
Expand Down Expand Up @@ -2216,6 +2262,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<bool> = (None, parse_opt_bool, [TRACKED],
"explicitly enable the `cfg(target_thread_local)` directive"),
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
Expand Down Expand Up @@ -2608,6 +2657,9 @@ written to standard error output)"),
"use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"),
write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED],
"whether long type names should be written to files instead of being printed in errors"),
x86_retpoline: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
"enable retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \
target features (default: no)"),
// tidy-alphabetical-end

// If you add a new option, please update:
Expand Down
54 changes: 53 additions & 1 deletion compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ pub enum Stability {
/// particular for features are actually ABI configuration flags (not all targets are as nice as
/// RISC-V and have an explicit way to set the ABI separate from target features).
Forbidden { reason: &'static str },
/// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set
/// by target modifier flag. Target modifier flags are tracked to be consistent in linked modules.
EnabledByTargetModifierFlag { reason: &'static str, flag: &'static str },
}
use Stability::*;

Expand All @@ -49,6 +52,7 @@ impl<CTX> HashStable<CTX> for Stability {
Stability::Forbidden { reason } => {
reason.hash_stable(hcx, hasher);
}
Stability::EnabledByTargetModifierFlag { .. } => {}
}
}
}
Expand All @@ -74,15 +78,23 @@ impl Stability {
Stability::Unstable(nightly_feature) => Some(nightly_feature),
Stability::Stable { .. } => None,
Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"),
Stability::EnabledByTargetModifierFlag { .. } => None,
}
}

/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
/// `requires_nightly`.)
pub fn toggle_allowed(&self) -> Result<(), &'static str> {
pub fn toggle_allowed(&self, flag_enabled: impl Fn(&str) -> bool) -> Result<(), &'static str> {
match self {
Stability::Forbidden { reason } => Err(reason),
Stability::EnabledByTargetModifierFlag { reason, flag } => {
if !flag_enabled(*flag) {
Err(reason)
} else {
Ok(())
}
}
_ => Ok(()),
}
}
Expand Down Expand Up @@ -409,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",
},
&[],
),
("kl", Unstable(sym::keylocker_x86), &["sse2"]),
("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
("lzcnt", Stable, &[]),
Expand All @@ -418,6 +446,30 @@ const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("prfchw", Unstable(sym::prfchw_target_feature), &[]),
("rdrand", Stable, &[]),
("rdseed", Stable, &[]),
(
"retpoline-external-thunk",
Stability::EnabledByTargetModifierFlag {
reason: "use `x86-retpoline` target modifier flag instead",
flag: "x86-retpoline",
},
&[],
),
(
"retpoline-indirect-branches",
Stability::EnabledByTargetModifierFlag {
reason: "use `x86-retpoline` target modifier flag instead",
flag: "x86-retpoline",
},
&[],
),
(
"retpoline-indirect-calls",
Stability::EnabledByTargetModifierFlag {
reason: "use `x86-retpoline` target modifier flag instead",
flag: "x86-retpoline",
},
&[],
),
("rtm", Unstable(sym::rtm_target_feature), &[]),
("sha", Stable, &["sse2"]),
("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),
Expand Down
34 changes: 34 additions & 0 deletions tests/codegen/harden-sls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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.

//@ 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{{.*}} }
}
27 changes: 27 additions & 0 deletions tests/codegen/retpoline.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// ignore-tidy-linelength
// Test that the
// `retpoline-external-thunk`, `retpoline-indirect-branches`, `retpoline-indirect-calls`
// target features are (not) emitted when the `x86-retpoline` flag is (not) set.

//@ revisions: disabled enabled
//@ needs-llvm-components: x86
//@ compile-flags: --target x86_64-unknown-linux-gnu
//@ [enabled] compile-flags: -Zx86-retpoline

#![crate_type = "lib"]
#![feature(no_core, lang_items)]
#![no_core]

#[lang = "sized"]
trait Sized {}

#[no_mangle]
pub fn foo() {
// CHECK: @foo() unnamed_addr #0

// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-external-thunk{{.*}} }
// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-branches{{.*}} }
// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-calls{{.*}} }

// enabled: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-external-thunk,+retpoline-indirect-branches,+retpoline-indirect-calls{{.*}} }
}
5 changes: 5 additions & 0 deletions tests/ui/check-cfg/target_feature.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`hard-float`
`hard-float-abi`
`hard-tp`
`harden-sls-ijmp`
`harden-sls-ret`
`hbc`
`high-registers`
`hvx`
Expand Down Expand Up @@ -182,6 +184,9 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`relax`
`relaxed-simd`
`reserve-x18`
`retpoline-external-thunk`
`retpoline-indirect-branches`
`retpoline-indirect-calls`
`rtm`
`sb`
`sha`
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/116344>

warning: 2 warnings emitted

14 changes: 14 additions & 0 deletions tests/ui/target-feature/harden-sls-target-feature-flag.rs
Original file line number Diff line number Diff line change
@@ -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 {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `x86-retpoline` 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 <https://github.com/rust-lang/rust/issues/116344>

warning: 1 warning emitted

Loading
Loading