Skip to content

Commit f3b9e41

Browse files
committed
-Zharden-sls flag (target modifier) added to enable mitigation against straight line speculation (SLS)
1 parent 69d4d5f commit f3b9e41

File tree

10 files changed

+194
-5
lines changed

10 files changed

+194
-5
lines changed

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
@@ -627,6 +627,7 @@ pub(crate) fn target_cpu(sess: &Session) -> &str {
627627
/// The target features for compiler flags other than `-Ctarget-features`.
628628
fn llvm_features_by_flags(sess: &Session, features: &mut Vec<String>) {
629629
target_features::retpoline_features_by_flags(sess, features);
630+
target_features::sls_features_by_flags(sess, features);
630631

631632
// -Zfixed-x18
632633
if sess.opts.unstable_opts.fixed_x18 {

compiler/rustc_codegen_ssa/src/target_features.rs

Lines changed: 13 additions & 0 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::lint::builtin::AARCH64_SOFTFLOAT_NEON;
1112
use rustc_session::parse::feature_err;
1213
use rustc_span::{Span, Symbol, sym};
@@ -415,6 +416,18 @@ pub fn retpoline_features_by_flags(sess: &Session, features: &mut Vec<String>) {
415416
}
416417
}
417418

419+
pub fn sls_features_by_flags(sess: &Session, features: &mut Vec<String>) {
420+
match &sess.opts.unstable_opts.harden_sls {
421+
HardenSls::None => (),
422+
HardenSls::All => {
423+
features.push("+harden-sls-ijmp".into());
424+
features.push("+harden-sls-ret".into());
425+
}
426+
HardenSls::Return => features.push("+harden-sls-ret".into()),
427+
HardenSls::IndirectJmp => features.push("+harden-sls-ijmp".into()),
428+
}
429+
}
430+
418431
pub(crate) fn provide(providers: &mut Providers) {
419432
*providers = Providers {
420433
rust_target_features: |tcx, cnum| {

compiler/rustc_session/src/config.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,11 +3295,11 @@ pub(crate) mod dep_tracking {
32953295
use super::{
32963296
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo,
32973297
CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug,
3298-
FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
3299-
LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OomStrategy,
3300-
OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius,
3301-
RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
3302-
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
3298+
FunctionReturn, HardenSls, InliningThreshold, InstrumentCoverage, InstrumentXRay,
3299+
LinkerPluginLto, LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload,
3300+
OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry,
3301+
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
3302+
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
33033303
};
33043304
use crate::lint;
33053305
use crate::utils::NativeLib;
@@ -3403,6 +3403,7 @@ pub(crate) mod dep_tracking {
34033403
Polonius,
34043404
InliningThreshold,
34053405
FunctionReturn,
3406+
HardenSls,
34063407
Align,
34073408
);
34083409

@@ -3657,6 +3658,16 @@ pub enum FunctionReturn {
36573658
ThunkExtern,
36583659
}
36593660

3661+
/// The different settings that the `-Zharden-sls` flag can have.
3662+
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
3663+
pub enum HardenSls {
3664+
#[default]
3665+
None,
3666+
All,
3667+
Return,
3668+
IndirectJmp,
3669+
}
3670+
36603671
/// Whether extra span comments are included when dumping MIR, via the `-Z mir-include-spans` flag.
36613672
/// By default, only enabled in the NLL MIR dumps, and disabled in all other passes.
36623673
#[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
@@ -876,6 +876,7 @@ mod desc {
876876
"either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
877877
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`)";
878878
pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`";
879+
pub(crate) const parse_harden_sls: &str = "`none`, `all`, `return` or `indirect-jmp`";
879880
pub(crate) const parse_wasm_c_abi: &str = "`spec`";
880881
pub(crate) const parse_mir_include_spans: &str =
881882
"either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)";
@@ -2033,6 +2034,17 @@ pub mod parse {
20332034
true
20342035
}
20352036

2037+
pub(crate) fn parse_harden_sls(slot: &mut HardenSls, v: Option<&str>) -> bool {
2038+
match v {
2039+
Some("none") => *slot = HardenSls::None,
2040+
Some("all") => *slot = HardenSls::All,
2041+
Some("return") => *slot = HardenSls::Return,
2042+
Some("indirect-jmp") => *slot = HardenSls::IndirectJmp,
2043+
_ => return false,
2044+
}
2045+
true
2046+
}
2047+
20362048
pub(crate) fn parse_wasm_c_abi(_slot: &mut (), v: Option<&str>) -> bool {
20372049
v == Some("spec")
20382050
}
@@ -2375,6 +2387,9 @@ options! {
23752387
graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
23762388
"use the given `fontname` in graphviz output; can be overridden by setting \
23772389
environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
2390+
harden_sls: HardenSls = (HardenSls::None, parse_harden_sls, [TRACKED TARGET_MODIFIER],
2391+
"flag to mitigate against straight line speculation (SLS) [none|all|return|indirect-jmp] \
2392+
(default: none)"),
23782393
has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
23792394
"explicitly enable the `cfg(target_thread_local)` directive"),
23802395
higher_ranked_assumptions: bool = (false, parse_bool, [TRACKED],

compiler/rustc_target/src/target_features.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,16 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
436436
("fma", Stable, &["avx"]),
437437
("fxsr", Stable, &[]),
438438
("gfni", Stable, &["sse2"]),
439+
(
440+
"harden-sls-ijmp",
441+
Stability::Forbidden { reason: "use `harden-sls` compiler flag instead" },
442+
&[],
443+
),
444+
(
445+
"harden-sls-ret",
446+
Stability::Forbidden { reason: "use `harden-sls` compiler flag instead" },
447+
&[],
448+
),
439449
("kl", Stable, &["sse2"]),
440450
("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
441451
("lzcnt", Stable, &[]),

tests/assembly-llvm/x86_64-sls.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Test harden-sls flag
2+
3+
#![feature(core_intrinsics)]
4+
//@ revisions: NONE ALL RET IJMP
5+
//@ assembly-output: emit-asm
6+
//@ compile-flags: -Copt-level=3 -Cunsafe-allow-abi-mismatch=harden-sls
7+
//@ [NONE] compile-flags: -Zharden-sls=none
8+
//@ [ALL] compile-flags: -Zharden-sls=all
9+
//@ [RET] compile-flags: -Zharden-sls=return
10+
//@ [IJMP] compile-flags: -Zharden-sls=indirect-jmp
11+
//@ only-x86_64
12+
#![crate_type = "lib"]
13+
14+
#[no_mangle]
15+
pub fn double_return(a: i32, b: i32) -> i32 {
16+
// CHECK-LABEL: double_return:
17+
// CHECK: jle
18+
// CHECK-NOT: int3
19+
// CHECK: retq
20+
// RET-NEXT: int3
21+
// ALL-NEXT: int3
22+
// IJMP-NOT: int3
23+
// NONE-NOT: int3
24+
// CHECK: retq
25+
// RET-NEXT: int3
26+
// ALL-NEXT: int3
27+
// IJMP-NOT: int3
28+
// NONE-NOT: int3
29+
if a > 0 {
30+
unsafe { std::intrinsics::unchecked_div(a, b) }
31+
} else {
32+
unsafe { std::intrinsics::unchecked_div(b, a) }
33+
}
34+
}
35+
36+
#[no_mangle]
37+
pub fn indirect_branch(a: i32, b: i32, i: i32) -> i32 {
38+
// CHECK-LABEL: indirect_branch:
39+
// CHECK: jmpq *
40+
// RET-NOT: int3
41+
// NONE-NOT: int3
42+
// IJMP-NEXT: int3
43+
// ALL-NEXT: int3
44+
// CHECK: retq
45+
// RET-NEXT: int3
46+
// ALL-NEXT: int3
47+
// IJMP-NOT: int3
48+
// NONE-NOT: int3
49+
// CHECK: retq
50+
// RET-NEXT: int3
51+
// ALL-NEXT: int3
52+
// IJMP-NOT: int3
53+
// NONE-NOT: int3
54+
match i {
55+
0 => unsafe { std::intrinsics::unchecked_div(a, b) },
56+
1 => unsafe { std::intrinsics::unchecked_div(b, a) },
57+
2 => unsafe { std::intrinsics::unchecked_div(b, a) + 2 },
58+
3 => unsafe { std::intrinsics::unchecked_div(b, a) + 3 },
59+
4 => unsafe { std::intrinsics::unchecked_div(b, a) + 4 },
60+
5 => unsafe { std::intrinsics::unchecked_div(b, a) + 5 },
61+
6 => unsafe { std::intrinsics::unchecked_div(b, a) + 6 },
62+
_ => panic!(""),
63+
}
64+
}
65+
66+
#[no_mangle]
67+
pub fn bar(ptr: fn()) {
68+
// CHECK-LABEL: bar:
69+
// CHECK: jmpq *
70+
// RET-NOT: int3
71+
// NONE-NOT: int3
72+
// IJMP-NEXT: int3
73+
// ALL-NEXT: int3
74+
// CHECK-NOT: ret
75+
ptr()
76+
}

tests/codegen-llvm/harden-sls.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// ignore-tidy-linelength
2+
// Test that the `harden-sls-ijmp`, `harden-sls-ret` target features is (not) emitted when
3+
// the `harden-sls=[none|all|return|indirect-jmp]` flag is (not) set.
4+
5+
//@ add-minicore
6+
//@ revisions: none all return indirect_jmp
7+
//@ needs-llvm-components: x86
8+
//@ compile-flags: --target x86_64-unknown-linux-gnu
9+
//@ [none] compile-flags: -Zharden-sls=none
10+
//@ [all] compile-flags: -Zharden-sls=all
11+
//@ [return] compile-flags: -Zharden-sls=return
12+
//@ [indirect_jmp] compile-flags: -Zharden-sls=indirect-jmp
13+
14+
#![crate_type = "lib"]
15+
#![feature(no_core)]
16+
#![no_core]
17+
18+
extern crate minicore;
19+
use minicore::*;
20+
21+
#[no_mangle]
22+
pub fn foo() {
23+
// CHECK: @foo() unnamed_addr #0
24+
25+
// none-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} }
26+
// none-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} }
27+
28+
// all: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp,+harden-sls-ret{{.*}} }
29+
30+
// return-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} }
31+
// return: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} }
32+
33+
// indirect_jmp-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ret{{.*}} }
34+
// indirect_jmp: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+harden-sls-ijmp{{.*}} }
35+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
warning: target feature `harden-sls-ijmp` cannot be enabled with `-Ctarget-feature`: use `harden-sls` compiler flag instead
2+
|
3+
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4+
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
5+
6+
warning: target feature `harden-sls-ret` cannot be enabled with `-Ctarget-feature`: use `harden-sls` compiler flag instead
7+
|
8+
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
9+
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
10+
11+
warning: 2 warnings emitted
12+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ add-minicore
2+
//@ revisions: by_flag by_feature
3+
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
4+
//@ needs-llvm-components: x86
5+
//@ [by_flag]compile-flags: -Zharden-sls=all
6+
//@ [by_feature]compile-flags: -Ctarget-feature=+harden-sls-ijmp,+harden-sls-ret
7+
//@ [by_flag]build-pass
8+
// For now this is just a warning.
9+
//@ [by_feature]build-pass
10+
#![feature(no_core, lang_items)]
11+
#![no_std]
12+
#![no_core]
13+
14+
//[by_feature]~? WARN target feature `harden-sls-ijmp` cannot be enabled with `-Ctarget-feature`: use `harden-sls` compiler flag instead
15+
//[by_feature]~? WARN target feature `harden-sls-ret` cannot be enabled with `-Ctarget-feature`: use `harden-sls` compiler flag instead

0 commit comments

Comments
 (0)