Skip to content

Commit 720aa1f

Browse files
committed
-Zharden-sls flag (target modifier) added to enable mitigation against straight line speculation (SLS)
1 parent 4feb722 commit 720aa1f

19 files changed

Lines changed: 320 additions & 31 deletions

File tree

compiler/rustc_codegen_gcc/src/gcc_util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_target::spec::Arch;
77

88
fn gcc_features_by_flags(sess: &Session, features: &mut Vec<String>) {
99
target_features::retpoline_features_by_flags(sess, features);
10+
target_features::sls_features_by_flags(sess, features);
1011
// FIXME: LLVM also sets +reserve-x18 here under some conditions.
1112
}
1213

compiler/rustc_codegen_llvm/src/llvm_util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ fn llvm_features_by_flags(sess: &Session, features: &mut Vec<String>) {
638638

639639
target_features::retpoline_features_by_flags(sess, features);
640640
target_features::sanitizer_features_by_flags(sess, features);
641+
target_features::sls_features_by_flags(sess, features);
641642

642643
// -Zfixed-x18
643644
if sess.opts.unstable_opts.fixed_x18 {

compiler/rustc_codegen_ssa/src/target_features.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_middle::middle::codegen_fn_attrs::{TargetFeature, TargetFeatureKind};
77
use rustc_middle::query::Providers;
88
use rustc_middle::ty::TyCtxt;
99
use rustc_session::Session;
10+
use rustc_session::config::HardenSls;
1011
use rustc_session::errors::feature_err;
1112
use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON;
1213
use rustc_span::{Span, Symbol, edit_distance, sym};
@@ -308,12 +309,18 @@ pub fn cfg_target_feature<'a, const N: usize>(
308309
sess.dcx().emit_warn(unknown_feature);
309310
}
310311
Some((_, stability, _)) => {
311-
if let Err(reason) = stability.toggle_allowed() {
312-
sess.dcx().emit_warn(errors::ForbiddenCTargetFeature {
312+
if let Stability::Forbidden { reason, hard_error } = stability {
313+
let diag = errors::ForbiddenCTargetFeature {
313314
feature: base_feature,
314315
enabled: if enable { "enabled" } else { "disabled" },
315316
reason,
316-
});
317+
};
318+
319+
if *hard_error {
320+
sess.dcx().emit_err(diag);
321+
} else {
322+
sess.dcx().emit_warn(diag);
323+
}
317324
} else if stability.requires_nightly(/* in_cfg */ false).is_some() {
318325
// An unstable feature. Warn about using it. It makes little sense
319326
// to hard-error here since we just warn about fully unknown
@@ -488,6 +495,18 @@ pub fn sanitizer_features_by_flags(sess: &Session, features: &mut Vec<String>) {
488495
}
489496
}
490497

498+
pub fn sls_features_by_flags(sess: &Session, features: &mut Vec<String>) {
499+
match &sess.opts.unstable_opts.harden_sls {
500+
HardenSls::None => (),
501+
HardenSls::All => {
502+
features.push("+harden-sls-ijmp".into());
503+
features.push("+harden-sls-ret".into());
504+
}
505+
HardenSls::Return => features.push("+harden-sls-ret".into()),
506+
HardenSls::IndirectJmp => features.push("+harden-sls-ijmp".into()),
507+
}
508+
}
509+
491510
pub(crate) fn provide(providers: &mut Providers) {
492511
*providers = Providers {
493512
rust_target_features: |tcx, cnum| {

compiler/rustc_session/src/config.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3069,10 +3069,11 @@ pub(crate) mod dep_tracking {
30693069
use super::{
30703070
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CoverageOptions,
30713071
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
3072-
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
3073-
LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel, OutFileName, OutputType,
3074-
OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks, SourceFileHashAlgorithm,
3075-
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
3072+
HardenSls, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
3073+
LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel,
3074+
OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks,
3075+
SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
3076+
WasiExecModel,
30763077
};
30773078
use crate::lint;
30783079
use crate::utils::NativeLib;
@@ -3175,6 +3176,7 @@ pub(crate) mod dep_tracking {
31753176
Polonius,
31763177
InliningThreshold,
31773178
FunctionReturn,
3179+
HardenSls,
31783180
Align,
31793181
);
31803182

@@ -3389,6 +3391,16 @@ pub enum FunctionReturn {
33893391
ThunkExtern,
33903392
}
33913393

3394+
/// The different settings that the `-Zharden-sls` flag can have.
3395+
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
3396+
pub enum HardenSls {
3397+
#[default]
3398+
None,
3399+
All,
3400+
Return,
3401+
IndirectJmp,
3402+
}
3403+
33923404
/// Whether extra span comments are included when dumping MIR, via the `-Z mir-include-spans` flag.
33933405
/// By default, only enabled in the NLL MIR dumps, and disabled in all other passes.
33943406
#[derive(Clone, Copy, Default, PartialEq, Debug)]

compiler/rustc_session/src/options.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,7 @@ mod desc {
834834
"either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
835835
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`)";
836836
pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`";
837+
pub(crate) const parse_harden_sls: &str = "`none`, `all`, `return` or `indirect-jmp`";
837838
pub(crate) const parse_wasm_c_abi: &str = "`spec`";
838839
pub(crate) const parse_mir_include_spans: &str =
839840
"either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)";
@@ -1986,6 +1987,17 @@ pub mod parse {
19861987
true
19871988
}
19881989

1990+
pub(crate) fn parse_harden_sls(slot: &mut HardenSls, v: Option<&str>) -> bool {
1991+
match v {
1992+
Some("none") => *slot = HardenSls::None,
1993+
Some("all") => *slot = HardenSls::All,
1994+
Some("return") => *slot = HardenSls::Return,
1995+
Some("indirect-jmp") => *slot = HardenSls::IndirectJmp,
1996+
_ => return false,
1997+
}
1998+
true
1999+
}
2000+
19892001
pub(crate) fn parse_wasm_c_abi(_slot: &mut (), v: Option<&str>) -> bool {
19902002
v == Some("spec")
19912003
}
@@ -2350,6 +2362,9 @@ options! {
23502362
graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
23512363
"use the given `fontname` in graphviz output; can be overridden by setting \
23522364
environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
2365+
harden_sls: HardenSls = (HardenSls::None, parse_harden_sls, [TRACKED] { TARGET_MODIFIER: HardenSls },
2366+
"flag to mitigate against straight line speculation (SLS) [none|all|return|indirect-jmp] \
2367+
(default: none)"),
23532368
has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
23542369
"explicitly enable the `cfg(target_thread_local)` directive"),
23552370
help: bool = (false, parse_no_value, [UNTRACKED], "Print unstable compiler options"),

compiler/rustc_target/src/target_features.rs

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! Note that these are similar to but not always identical to LLVM's feature names,
33
//! and Rust adds some features that do not correspond to LLVM features at all.
44
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5-
use rustc_macros::StableHash;
5+
use rustc_data_structures::stable_hasher::{StableHash, StableHashCtxt, StableHasher};
66
use rustc_span::{Symbol, sym};
77

88
use crate::spec::{Arch, FloatAbi, LlvmAbi, RustcAbi, Target};
@@ -12,7 +12,7 @@ use crate::spec::{Arch, FloatAbi, LlvmAbi, RustcAbi, Target};
1212
pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
1313

1414
/// Stability information for target features.
15-
#[derive(Debug, Copy, Clone, StableHash)]
15+
#[derive(Debug, Copy, Clone)]
1616
pub enum Stability {
1717
/// This target feature is stable, it can be used in `#[target_feature]` and
1818
/// `#[cfg(target_feature)]`.
@@ -35,10 +35,35 @@ pub enum Stability {
3535
/// set in the target spec. It is never set in `cfg(target_feature)`. Used in
3636
/// particular for features are actually ABI configuration flags (not all targets are as nice as
3737
/// RISC-V and have an explicit way to set the ABI separate from target features).
38-
Forbidden { reason: &'static str },
38+
Forbidden {
39+
reason: &'static str,
40+
/// True if this is always an error, false if this can be reported as a warning when set via
41+
/// `-Ctarget-feature`.
42+
hard_error: bool,
43+
},
3944
}
4045
use Stability::*;
4146

47+
impl StableHash for Stability {
48+
#[inline]
49+
fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
50+
std::mem::discriminant(self).stable_hash(hcx, hasher);
51+
match self {
52+
Stability::Stable => {}
53+
Stability::Unstable(nightly_feature) => {
54+
nightly_feature.stable_hash(hcx, hasher);
55+
}
56+
Stability::CfgStableToggleUnstable(nightly_feature) => {
57+
nightly_feature.stable_hash(hcx, hasher);
58+
}
59+
Stability::Forbidden { reason, hard_error } => {
60+
reason.stable_hash(hcx, hasher);
61+
hard_error.stable_hash(hcx, hasher);
62+
}
63+
}
64+
}
65+
}
66+
4267
impl Stability {
4368
/// Returns whether the feature can be used in `cfg(target_feature)` ever.
4469
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
@@ -85,14 +110,14 @@ impl Stability {
85110
}
86111

87112
/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
88-
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
113+
/// (It might still be nightly-only even if this returns `Ok(())`, so make sure to also check
89114
/// `requires_nightly`.)
90115
pub fn toggle_allowed(&self) -> Result<(), &'static str> {
91116
match self {
92117
Stability::Unstable(_)
93118
| Stability::CfgStableToggleUnstable(_)
94119
| Stability::Stable { .. } => Ok(()),
95-
Stability::Forbidden { reason } => Err(reason),
120+
Stability::Forbidden { reason, hard_error: _ } => Err(reason),
96121
}
97122
}
98123
}
@@ -149,7 +174,10 @@ static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
149174
("aes", Unstable(sym::arm_target_feature), &["neon"]),
150175
(
151176
"atomics-32",
152-
Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
177+
Stability::Forbidden {
178+
reason: "unsound because it changes the ABI of atomic operations",
179+
hard_error: false,
180+
},
153181
&[],
154182
),
155183
("crc", Unstable(sym::arm_target_feature), &[]),
@@ -225,7 +253,11 @@ static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
225253
// FEAT_FLAGM2
226254
("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]),
227255
// We forbid directly toggling just `fp-armv8`; it must be toggled with `neon`.
228-
("fp-armv8", Stability::Forbidden { reason: "Rust ties `fp-armv8` to `neon`" }, &[]),
256+
(
257+
"fp-armv8",
258+
Stability::Forbidden { reason: "Rust ties `fp-armv8` to `neon`", hard_error: false },
259+
&[],
260+
),
229261
// FEAT_FP8
230262
("fp8", Unstable(sym::aarch64_unstable_target_feature), &["faminmax", "lut", "bf16"]),
231263
// FEAT_FP8DOT2
@@ -288,7 +320,11 @@ static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
288320
("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]),
289321
// FEAT_RDM
290322
("rdm", Stable, &["neon"]),
291-
("reserve-x18", Forbidden { reason: "use `-Zfixed-x18` compiler flag instead" }, &[]),
323+
(
324+
"reserve-x18",
325+
Forbidden { reason: "use `-Zfixed-x18` compiler flag instead", hard_error: false },
326+
&[],
327+
),
292328
// FEAT_SB
293329
("sb", Stable, &[]),
294330
// FEAT_SHA1 & FEAT_SHA256
@@ -455,6 +491,16 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
455491
("fma4", Unstable(sym::fma4_target_feature), &["avx", "sse4a"]),
456492
("fxsr", Stable, &[]),
457493
("gfni", Stable, &["sse2"]),
494+
(
495+
"harden-sls-ijmp",
496+
Stability::Forbidden { reason: "use `harden-sls` compiler flag instead", hard_error: true },
497+
&[],
498+
),
499+
(
500+
"harden-sls-ret",
501+
Stability::Forbidden { reason: "use `harden-sls` compiler flag instead", hard_error: true },
502+
&[],
503+
),
458504
("kl", Stable, &["sse2"]),
459505
("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
460506
("lzcnt", Stable, &[]),
@@ -467,25 +513,38 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
467513
("rdseed", Stable, &[]),
468514
(
469515
"retpoline-external-thunk",
470-
Stability::Forbidden { reason: "use `-Zretpoline-external-thunk` compiler flag instead" },
516+
Stability::Forbidden {
517+
reason: "use `-Zretpoline-external-thunk` compiler flag instead",
518+
hard_error: false,
519+
},
471520
&[],
472521
),
473522
(
474523
"retpoline-indirect-branches",
475-
Stability::Forbidden { reason: "use `-Zretpoline` compiler flag instead" },
524+
Stability::Forbidden {
525+
reason: "use `-Zretpoline` compiler flag instead",
526+
hard_error: false,
527+
},
476528
&[],
477529
),
478530
(
479531
"retpoline-indirect-calls",
480-
Stability::Forbidden { reason: "use `-Zretpoline` compiler flag instead" },
532+
Stability::Forbidden {
533+
reason: "use `-Zretpoline` compiler flag instead",
534+
hard_error: false,
535+
},
481536
&[],
482537
),
483538
("rtm", Unstable(sym::rtm_target_feature), &[]),
484539
("sha", Stable, &["sse2"]),
485540
("sha512", Stable, &["avx2"]),
486541
("sm3", Stable, &["avx"]),
487542
("sm4", Stable, &["avx2"]),
488-
("soft-float", Stability::Forbidden { reason: "use a soft-float target instead" }, &[]),
543+
(
544+
"soft-float",
545+
Stability::Forbidden { reason: "use a soft-float target instead", hard_error: false },
546+
&[],
547+
),
489548
("sse", Stable, &[]),
490549
("sse2", Stable, &["sse"]),
491550
("sse3", Stable, &["sse2"]),
@@ -615,7 +674,10 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
615674
("f", Unstable(sym::riscv_target_feature), &["zicsr"]),
616675
(
617676
"forced-atomics",
618-
Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
677+
Stability::Forbidden {
678+
reason: "unsound because it changes the ABI of atomic operations",
679+
hard_error: false,
680+
},
619681
&[],
620682
),
621683
("m", Stable, &[]),
@@ -872,7 +934,7 @@ const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
872934
("miscellaneous-extensions-3", Stable, &[]),
873935
("miscellaneous-extensions-4", Stable, &[]),
874936
("nnp-assist", Stable, &["vector"]),
875-
("soft-float", Forbidden { reason: "unsupported ABI-configuration feature" }, &[]),
937+
("soft-float", Forbidden { reason: "unsupported ABI-configuration feature", hard_error: false }, &[]),
876938
("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
877939
("vector", Stable, &[]),
878940
("vector-enhancements-1", Stable, &["vector"]),
@@ -924,7 +986,11 @@ static AVR_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
924986
("rmw", Unstable(sym::avr_target_feature), &[]),
925987
("spm", Unstable(sym::avr_target_feature), &[]),
926988
("spmx", Unstable(sym::avr_target_feature), &[]),
927-
("sram", Forbidden { reason: "devices that have no SRAM are unsupported" }, &[]),
989+
(
990+
"sram",
991+
Forbidden { reason: "devices that have no SRAM are unsupported", hard_error: false },
992+
&[],
993+
),
928994
("tinyencoding", Unstable(sym::avr_target_feature), &[]),
929995
// tidy-alphabetical-end
930996
];

src/doc/rustc-dev-guide/src/tests/directives.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,14 @@ See also [Debuginfo tests](compiletest.md#debuginfo-tests) for directives for ig
244244

245245
| Directive | Explanation | Supported test suites | Possible values |
246246
|---------------------|----------------------------------------------------------------------------------------------|--------------------------------------------|--------------------------------------------------------------------------------------------|
247-
| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make`/`run-make-cargo` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
248-
| `edition` | The edition used to build the test | All except for `run-make`/`run-make-cargo` | Any valid `--edition` value |
249-
| `rustc-env` | Env var to set when running `rustc` | All except for `run-make`/`run-make-cargo` | `<KEY>=<VALUE>` |
250-
| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make`/`run-make-cargo` | Any env var name |
251-
| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A |
252-
| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A |
247+
| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make`/`run-make-cargo` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
248+
| `minicore-compile-flags` | Additional flags passed to `rustc` when building minicore | All except for `run-make`/`run-make-cargo` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
249+
| `non-aux-compile-flags` | Additional flags passed to `rustc` when building the test (not for auxiliary builds) | All except for `run-make`/`run-make-cargo` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` |
250+
| `edition` | The edition used to build the test | All except for `run-make`/`run-make-cargo` | Any valid `--edition` value |
251+
| `rustc-env` | Env var to set when running `rustc` | All except for `run-make`/`run-make-cargo` | `<KEY>=<VALUE>` |
252+
| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make`/`run-make-cargo` | Any env var name |
253+
| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A |
254+
| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A |
253255

254256
<div class="warning">
255257

src/doc/rustc-dev-guide/src/tests/minicore.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ The `minicore` items must be kept up to date with `core`.
4444
For consistent diagnostic output between using `core` and `minicore`, any `diagnostic`
4545
attributes (e.g. `on_unimplemented`) should be replicated exactly in `minicore`.
4646

47+
## Specific compile flags
48+
`compile-flags` is used both for auxiliary builds (including minicore) and main test build.
49+
`minicore-compile-flags` directive may be used to provide compile flags for minicore build only.
50+
`non-aux-compile-flags` directive may be used to provide compile flags for main test only.
51+
4752
## Example codegen test that uses `minicore`
4853

4954
```rust,no_run

0 commit comments

Comments
 (0)