2023-10-23 17:45:49

by Miguel Ojeda

[permalink] [raw]
Subject: [PATCH 1/4] x86/rust: support RETPOLINE

Support the `RETPOLINE` speculation mitigation by enabling the target
features that Clang does.

The existing target feature being enabled was a leftover from
our old `rust` branch, and it is not enough: the target feature
`retpoline-external-thunk` only implies `retpoline-indirect-calls`, but
not `retpoline-indirect-branches` (see LLVM's `X86.td`), unlike Clang's
flag of the same name `-mretpoline-external-thunk` which does imply both
(see Clang's `lib/Driver/ToolChains/Arch/X86.cpp`).

Without this, `objtool` would complain if enabled for individual object
files (like it is planned in the future), e.g.

rust/core.o: warning: objtool:
_R...escape_default+0x13: indirect jump found in RETPOLINE build

In addition, change the comment to note that LLVM is the one disabling
jump tables when retpoline is enabled, thus we do not need to use
`-Zno-jump-tables` for Rust here -- see commit c58f2166ab39 ("Introduce
the "retpoline" x86 mitigation technique ...") [1]:

The goal is simple: avoid generating code which contains an indirect
branch that could have its prediction poisoned by an attacker. In
many cases, the compiler can simply use directed conditional
branches and a small search tree. LLVM already has support for
lowering switches in this way and the first step of this patch is
to disable jump-table lowering of switches and introduce a pass to
rewrite explicit indirectbr sequences into a switch over integers.

As well as a live example at [2].

Cc: Daniel Borkmann <[email protected]>
Link: https://github.com/llvm/llvm-project/commit/c58f2166ab3987f37cb0d7815b561bff5a20a69a [1]
Link: https://godbolt.org/z/esT8xnaxj [2]
Signed-off-by: Miguel Ojeda <[email protected]>
---
arch/x86/Makefile | 2 +-
scripts/generate_rust_target.rs | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 5bfe5caaa444..3df7c7c81918 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -195,7 +195,7 @@ ifdef CONFIG_RETPOLINE
KBUILD_CFLAGS += $(RETPOLINE_CFLAGS)
# Additionally, avoid generating expensive indirect jumps which
# are subject to retpolines for small number of switch cases.
- # clang turns off jump table generation by default when under
+ # LLVM turns off jump table generation by default when under
# retpoline builds, however, gcc does not for x86. This has
# only been fixed starting from gcc stable version 8.4.0 and
# onwards, but not for older ones. See gcc bug #86952.
diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs
index 3c6cbe2b278d..163089ae13ba 100644
--- a/scripts/generate_rust_target.rs
+++ b/scripts/generate_rust_target.rs
@@ -156,7 +156,14 @@ fn main() {
);
let mut features = "-3dnow,-3dnowa,-mmx,+soft-float".to_string();
if cfg.has("RETPOLINE") {
+ // The kernel uses `-mretpoline-external-thunk` (for Clang), which Clang maps to the
+ // target feature of the same name plus the other two target features in
+ // `clang/lib/Driver/ToolChains/Arch/X86.cpp`. These should be eventually enabled via
+ // `-Ctarget-feature` when `rustc` starts recognizing them (or via a new dedicated
+ // flag); see https://github.com/rust-lang/rust/issues/116852.
features += ",+retpoline-external-thunk";
+ features += ",+retpoline-indirect-branches";
+ features += ",+retpoline-indirect-calls";
}
ts.push("features", features);
ts.push("llvm-target", "x86_64-linux-gnu");

base-commit: 58720809f52779dc0f08e53e54b014209d13eebb
--
2.42.0


2023-10-23 17:46:15

by Miguel Ojeda

[permalink] [raw]
Subject: [PATCH 2/4] x86/rust: support SLS

Support the `SLS` speculation mitigation by enabling the target features
that Clang does.

Without this, `objtool` would complain if enabled for individual object
files (like it is planned in the future), e.g.

rust/core.o: warning: objtool:
_R...next_up+0x44: missing int3 after ret

Signed-off-by: Miguel Ojeda <[email protected]>
---
scripts/generate_rust_target.rs | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs
index 163089ae13ba..7e374369afca 100644
--- a/scripts/generate_rust_target.rs
+++ b/scripts/generate_rust_target.rs
@@ -165,6 +165,14 @@ fn main() {
features += ",+retpoline-indirect-branches";
features += ",+retpoline-indirect-calls";
}
+ if cfg.has("SLS") {
+ // The kernel uses `-mharden-sls=all`, which Clang maps to both these target features in
+ // `clang/lib/Driver/ToolChains/Arch/X86.cpp`. These should be eventually enabled via
+ // `-Ctarget-feature` when `rustc` starts recognizing them (or via a new dedicated
+ // flag); see https://github.com/rust-lang/rust/issues/116851.
+ features += ",+harden-sls-ijmp";
+ features += ",+harden-sls-ret";
+ }
ts.push("features", features);
ts.push("llvm-target", "x86_64-linux-gnu");
ts.push("target-pointer-width", "64");
--
2.42.0

2023-10-23 17:46:22

by Miguel Ojeda

[permalink] [raw]
Subject: [PATCH 3/4] x86/rust: depend on !RETHUNK

The Rust compiler does not support the equivalent of
`-mfunction-return=thunk-extern` yet [1]. Thus, currently, `objtool`
warns about it, e.g.:

samples/rust/rust_print.o: warning: objtool: _R...init+0xa5c:
'naked' return found in RETHUNK build

The support in `rustc` for `-Zfunction-return` has been submitted and
is being reviewed [2]. It adds the needed LLVM function attributes and,
with it, I got a RETHUNK kernel build with Rust enabled that does not
print the `objtool` related warnings, boots in QEMU and can load a kernel
loadable module.

In any case, until proper/complete support is added to `rustc`, make it
a hard restriction until the mitigation is in place.

This may have an impact for developers that may not need/care about the
mitigation in the Rust side (e.g. Ubuntu offers Rust as a "technology
preview" [3]), but given we are getting closer to having the first actual
in-tree Rust kernel users, it seems like the right time to disallow
it. This should also avoid confusion [4].

Link: https://github.com/rust-lang/rust/issues/116853 [1]
Link: https://github.com/rust-lang/rust/pull/116892 [2]
Link: https://lore.kernel.org/rust-for-linux/ZSQXqX2%2Flhf5ICZP@gpd/ [3]
Link: https://lore.kernel.org/rust-for-linux/CANiq72n6DMeXQrgOzS_+3VdgNYAmpcnneAHJnZERUQhMExg+0A@mail.gmail.com/ [4]
Signed-off-by: Miguel Ojeda <[email protected]>
---
init/Kconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/init/Kconfig b/init/Kconfig
index 6d35728b94b2..9452b4102b99 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1889,6 +1889,7 @@ config RUST
depends on !GCC_PLUGINS
depends on !RANDSTRUCT
depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
+ depends on !RETHUNK
select CONSTRUCTORS
help
Enables Rust support in the kernel.
--
2.42.0

2023-10-23 17:46:28

by Miguel Ojeda

[permalink] [raw]
Subject: [RFC PATCH 4/4] x86/rust: support RETHUNK

When support for `-Zfunction-return` lands in Rust [1], this patch may
be used to enable RETHUNK support on top of the previous patch.

Link: https://github.com/rust-lang/rust/pull/116892 [1]
Signed-off-by: Miguel Ojeda <[email protected]>
---
Note that this patch is not meant to be applied now, it is only here to
show what will be needed to drop the depends on from the previous patch.

arch/x86/Makefile | 5 +++++
init/Kconfig | 1 -
2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 3df7c7c81918..818fdb1a92c5 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -24,11 +24,15 @@ RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch-cs-prefix)

ifdef CONFIG_RETHUNK
RETHUNK_CFLAGS := -mfunction-return=thunk-extern
+RETHUNK_RUSTFLAGS := -Zfunction-return=thunk-extern
RETPOLINE_CFLAGS += $(RETHUNK_CFLAGS)
+RETPOLINE_RUSTFLAGS += $(RETHUNK_RUSTFLAGS)
endif

export RETHUNK_CFLAGS
+export RETHUNK_RUSTFLAGS
export RETPOLINE_CFLAGS
+export RETPOLINE_RUSTFLAGS
export RETPOLINE_VDSO_CFLAGS

# For gcc stack alignment is specified with -mpreferred-stack-boundary,
@@ -193,6 +197,7 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
# Avoid indirect branches in kernel to deal with Spectre
ifdef CONFIG_RETPOLINE
KBUILD_CFLAGS += $(RETPOLINE_CFLAGS)
+ KBUILD_RUSTFLAGS += $(RETPOLINE_RUSTFLAGS)
# Additionally, avoid generating expensive indirect jumps which
# are subject to retpolines for small number of switch cases.
# LLVM turns off jump table generation by default when under
diff --git a/init/Kconfig b/init/Kconfig
index 9452b4102b99..6d35728b94b2 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1889,7 +1889,6 @@ config RUST
depends on !GCC_PLUGINS
depends on !RANDSTRUCT
depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
- depends on !RETHUNK
select CONSTRUCTORS
help
Enables Rust support in the kernel.
--
2.42.0

Subject: Re: [PATCH 3/4] x86/rust: depend on !RETHUNK

On 10/23/23 14:44, Miguel Ojeda wrote:
> The Rust compiler does not support the equivalent of
> `-mfunction-return=thunk-extern` yet [1]. Thus, currently, `objtool`
> warns about it, e.g.:
>
> samples/rust/rust_print.o: warning: objtool: _R...init+0xa5c:
> 'naked' return found in RETHUNK build
>
> The support in `rustc` for `-Zfunction-return` has been submitted and
> is being reviewed [2]. It adds the needed LLVM function attributes and,
> with it, I got a RETHUNK kernel build with Rust enabled that does not
> print the `objtool` related warnings, boots in QEMU and can load a kernel
> loadable module.
>
> In any case, until proper/complete support is added to `rustc`, make it
> a hard restriction until the mitigation is in place.
>
> This may have an impact for developers that may not need/care about the
> mitigation in the Rust side (e.g. Ubuntu offers Rust as a "technology
> preview" [3]), but given we are getting closer to having the first actual
> in-tree Rust kernel users, it seems like the right time to disallow
> it. This should also avoid confusion [4].

I'll mention that I've tested boots, both in bare metal and QEMU, with
`RUST=y` and `RETHUNK=y` and they were alright regardless of `objtool`
warnings. Although, if you had an issue in the past then I'd like to know
about it.

2023-10-23 22:16:18

by Miguel Ojeda

[permalink] [raw]
Subject: Re: [PATCH 3/4] x86/rust: depend on !RETHUNK

On Mon, Oct 23, 2023 at 8:43 PM Martin Rodriguez Reboredo
<[email protected]> wrote:
>
> I'll mention that I've tested boots, both in bare metal and QEMU, with
> `RUST=y` and `RETHUNK=y` and they were alright regardless of `objtool`
> warnings. Although, if you had an issue in the past then I'd like to know
> about it.

These are mitigations -- things do functionally work if they are not
applied, but you would be vulnerable.

In other words, it is not like e.g. IBT where you could have noticed
it breaking by running it normally if you happened to have a supported
platform.

Cheers,
Miguel

Subject: Re: [PATCH 3/4] x86/rust: depend on !RETHUNK

On 10/23/23 19:15, Miguel Ojeda wrote:
> On Mon, Oct 23, 2023 at 8:43 PM Martin Rodriguez Reboredo
> <[email protected]> wrote:
>>
>> I'll mention that I've tested boots, both in bare metal and QEMU, with
>> `RUST=y` and `RETHUNK=y` and they were alright regardless of `objtool`
>> warnings. Although, if you had an issue in the past then I'd like to know
>> about it.
>
> These are mitigations -- things do functionally work if they are not
> applied, but you would be vulnerable.
>
> In other words, it is not like e.g. IBT where you could have noticed
> it breaking by running it normally if you happened to have a supported
> platform.
>
> Cheers,
> Miguel

'Guess you have a point...

Acked-by: Martin Rodriguez Reboredo <[email protected]>

2023-10-28 17:52:52

by Miguel Ojeda

[permalink] [raw]
Subject: Re: [PATCH 3/4] x86/rust: depend on !RETHUNK

On Mon, Oct 23, 2023 at 7:45 PM Miguel Ojeda <[email protected]> wrote:
>
> The Rust compiler does not support the equivalent of
> `-mfunction-return=thunk-extern` yet [1]. Thus, currently, `objtool`
> warns about it, e.g.:

I just realized I did not Cc Andrea when I sent this, which was my
intention -- done here, sorry!

Cheers,
Miguel

2024-01-28 18:27:07

by Miguel Ojeda

[permalink] [raw]
Subject: Re: [PATCH 1/4] x86/rust: support RETPOLINE

On Mon, Oct 23, 2023 at 7:45 PM Miguel Ojeda <[email protected]> wrote:
>
> Support the `RETPOLINE` speculation mitigation by enabling the target
> features that Clang does.

x86: do you plan/want to pick this series up?

Thanks!

Cheers,
Miguel