Replace the funny __warn_thunk thing with a more regular
WARN_ON_ONCE(), and simplify the ifdeffery.
Notably this avoids RET from having recursive RETs (once from the
thunk and once from the C function) -- recursive RET makes my head
hurt for no good reason.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/x86/entry/entry.S | 3 ---
arch/x86/include/asm/nospec-branch.h | 2 --
arch/x86/kernel/cpu/bugs.c | 5 -----
arch/x86/lib/retpoline.S | 20 ++++++++++++--------
4 files changed, 12 insertions(+), 18 deletions(-)
--- a/arch/x86/entry/entry.S
+++ b/arch/x86/entry/entry.S
@@ -10,8 +10,6 @@
#include <asm/segment.h>
#include <asm/cache.h>
-#include "calling.h"
-
.pushsection .noinstr.text, "ax"
SYM_FUNC_START(entry_ibpb)
@@ -45,4 +43,3 @@ EXPORT_SYMBOL_GPL(mds_verw_sel);
.popsection
-THUNK warn_thunk_thunk, __warn_thunk
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -387,8 +387,6 @@ extern void clear_bhb_loop(void);
extern void (*x86_return_thunk)(void);
-extern void __warn_thunk(void);
-
#ifdef CONFIG_MITIGATION_CALL_DEPTH_TRACKING
extern void call_depth_return_thunk(void);
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -3025,8 +3025,3 @@ ssize_t cpu_show_reg_file_data_sampling(
return cpu_show_common(dev, attr, buf, X86_BUG_RFDS);
}
#endif
-
-void __warn_thunk(void)
-{
- WARN_ONCE(1, "Unpatched return thunk in use. This should not happen!\n");
-}
--- a/arch/x86/lib/retpoline.S
+++ b/arch/x86/lib/retpoline.S
@@ -12,9 +12,14 @@
#include <asm/percpu.h>
#include <asm/frame.h>
#include <asm/nops.h>
+#include <asm/bug.h>
- .section .text..__x86.indirect_thunk
+#define WARN_ONCE \
+ 1: ALTERNATIVE "", "ud2", X86_FEATURE_ALWAYS ; \
+ ASM_BUGTABLE_FLAGS(1b, 0, 0, BUGFLAG_WARNING | BUGFLAG_ONCE) ; \
+ REACHABLE
+ .section .text..__x86.indirect_thunk
.macro POLINE reg
ANNOTATE_INTRA_FUNCTION_CALL
@@ -382,16 +387,15 @@ SYM_FUNC_END(call_depth_return_thunk)
SYM_CODE_START(__x86_return_thunk)
UNWIND_HINT_FUNC
ANNOTATE_NOENDBR
-#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \
- defined(CONFIG_MITIGATION_SRSO) || \
- defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING)
- ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \
- "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS
-#else
+
+#ifdef CONFIG_X86_64
+ WARN_ONCE
+#endif
+
ANNOTATE_UNRET_SAFE
ret
-#endif
int3
+
SYM_CODE_END(__x86_return_thunk)
EXPORT_SYMBOL(__x86_return_thunk)
On Mon, Oct 07, 2024 at 10:32:12AM +0200, Peter Zijlstra wrote: > - .section .text..__x86.indirect_thunk > +#define WARN_ONCE \ This should be in the asm section of arch/x86/include/asm/bug.h so that other asm code can use it. It will come in handy... > + 1: ALTERNATIVE "", "ud2", X86_FEATURE_ALWAYS ; \ ... but uff, you can't because of this ALTERNATIVE. This is a conditional WARN_ONCE. Yuck. I guess ALT_WARN_ONCE or so... > + ASM_BUGTABLE_FLAGS(1b, 0, 0, BUGFLAG_WARNING | BUGFLAG_ONCE) ; \ > + REACHABLE > > + .section .text..__x86.indirect_thunk > > .macro POLINE reg > ANNOTATE_INTRA_FUNCTION_CALL > @@ -382,16 +387,15 @@ SYM_FUNC_END(call_depth_return_thunk) > SYM_CODE_START(__x86_return_thunk) > UNWIND_HINT_FUNC > ANNOTATE_NOENDBR > -#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \ > - defined(CONFIG_MITIGATION_SRSO) || \ > - defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) > - ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \ > - "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS > -#else > + > +#ifdef CONFIG_X86_64 > + WARN_ONCE > +#endif And you can add an empty 32-bit WARN_ONCE macro so that we don't have this ifdeffery here where ifdeffery gives the last drop of making this file totally unreadable... -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette
On Mon, Nov 04, 2024 at 12:47:28PM +0100, Borislav Petkov wrote: > On Mon, Oct 07, 2024 at 10:32:12AM +0200, Peter Zijlstra wrote: > > - .section .text..__x86.indirect_thunk > > +#define WARN_ONCE \ > > This should be in the asm section of arch/x86/include/asm/bug.h so that other > asm code can use it. It will come in handy... > > > + 1: ALTERNATIVE "", "ud2", X86_FEATURE_ALWAYS ; \ > > ... but uff, you can't because of this ALTERNATIVE. This is a conditional > WARN_ONCE. Yuck. > > I guess ALT_WARN_ONCE or so... Yeah, Josh already said similar things. > > + ASM_BUGTABLE_FLAGS(1b, 0, 0, BUGFLAG_WARNING | BUGFLAG_ONCE) ; \ > > + REACHABLE > > > > + .section .text..__x86.indirect_thunk > > > > .macro POLINE reg > > ANNOTATE_INTRA_FUNCTION_CALL > > @@ -382,16 +387,15 @@ SYM_FUNC_END(call_depth_return_thunk) > > SYM_CODE_START(__x86_return_thunk) > > UNWIND_HINT_FUNC > > ANNOTATE_NOENDBR > > -#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \ > > - defined(CONFIG_MITIGATION_SRSO) || \ > > - defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) > > - ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \ > > - "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS > > -#else > > + > > +#ifdef CONFIG_X86_64 > > + WARN_ONCE > > +#endif > > And you can add an empty 32-bit WARN_ONCE macro so that we don't have this > ifdeffery here where ifdeffery gives the last drop of making this file totally > unreadable... I just realized all the rethunk crap is 64bit only anyway. So it don't matter. But the reason I did this is that we never rewrite thunk calls on 32bit (really, we should just strip all mitigation shit from it and leave it to rot).
On Mon, Nov 04, 2024 at 03:29:53PM +0100, Peter Zijlstra wrote: > I just realized all the rethunk crap is 64bit only anyway. So it don't > matter. > > But the reason I did this is that we never rewrite thunk calls on 32bit > (really, we should just strip all mitigation shit from it and leave it > to rot). Perfectly fine with me. -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette
On Mon, Oct 07, 2024 at 10:32:12AM +0200, Peter Zijlstra wrote: > Replace the funny __warn_thunk thing with a more regular > WARN_ON_ONCE(), and simplify the ifdeffery. > > Notably this avoids RET from having recursive RETs (once from the > thunk and once from the C function) -- recursive RET makes my head > hurt for no good reason. This could use an explanation for why the ifdefs can be removed and why the alternative can be removed. > +#define WARN_ONCE \ > + 1: ALTERNATIVE "", "ud2", X86_FEATURE_ALWAYS ; \ > + ASM_BUGTABLE_FLAGS(1b, 0, 0, BUGFLAG_WARNING | BUGFLAG_ONCE) ; \ > + REACHABLE Can we not use __FILE__ and __LINE__ here? Also why not put this in asm/bug.h? > SYM_CODE_START(__x86_return_thunk) > UNWIND_HINT_FUNC > ANNOTATE_NOENDBR > -#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \ > - defined(CONFIG_MITIGATION_SRSO) || \ > - defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) > - ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \ > - "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS > -#else > + > +#ifdef CONFIG_X86_64 > + WARN_ONCE > +#endif Isn't this return thunk used before apply_returns()? How does that not trigger the warning? -- Josh
On Mon, Oct 07, 2024 at 10:33:45AM -0700, Josh Poimboeuf wrote: > On Mon, Oct 07, 2024 at 10:32:12AM +0200, Peter Zijlstra wrote: > > Replace the funny __warn_thunk thing with a more regular > > WARN_ON_ONCE(), and simplify the ifdeffery. > > > > Notably this avoids RET from having recursive RETs (once from the > > thunk and once from the C function) -- recursive RET makes my head > > hurt for no good reason. > > This could use an explanation for why the ifdefs can be removed and why > the alternative can be removed. The alternative is in the WARN_ONCE now. > > +#define WARN_ONCE \ > > + 1: ALTERNATIVE "", "ud2", X86_FEATURE_ALWAYS ; \ > > + ASM_BUGTABLE_FLAGS(1b, 0, 0, BUGFLAG_WARNING | BUGFLAG_ONCE) ; \ > > + REACHABLE > > Can we not use __FILE__ and __LINE__ here? Because for asm, __FILE__ is spelled like: #ifdef CONFIG_DEBUG_BUGVERBOSE .pushsection .rodata.str1.1, "aMS",@progbits,1 .LC0: .string __FILE__ .popsection #endif 1: ALTERNATIVE "", "ud2", X86_FEATURE_ALWAYS ASM_BUGTABLE_FLAGS(1b, LC0b, __LINE__, BUGFLAG_WARNING | BUGFLAG_ONCE) REACHABLE And I didn't feel the whole thing was worth the trouble, if NULL bug will only print the symbol name and that should be clear enough. > Also why not put this in asm/bug.h? Because the ALTERNATIVE.. > > SYM_CODE_START(__x86_return_thunk) > > UNWIND_HINT_FUNC > > ANNOTATE_NOENDBR > > -#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \ > > - defined(CONFIG_MITIGATION_SRSO) || \ > > - defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) > > - ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \ > > - "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS > > -#else > > + > > +#ifdef CONFIG_X86_64 > > + WARN_ONCE > > +#endif > > Isn't this return thunk used before apply_returns()? How does that not > trigger the warning? You missed the ALTERNATIVE I squirreled away in the WARN thing :-)
On Tue, Oct 08, 2024 at 09:25:02AM +0200, Peter Zijlstra wrote: > On Mon, Oct 07, 2024 at 10:33:45AM -0700, Josh Poimboeuf wrote: > > On Mon, Oct 07, 2024 at 10:32:12AM +0200, Peter Zijlstra wrote: > > > Replace the funny __warn_thunk thing with a more regular > > > WARN_ON_ONCE(), and simplify the ifdeffery. > > > > > > Notably this avoids RET from having recursive RETs (once from the > > > thunk and once from the C function) -- recursive RET makes my head > > > hurt for no good reason. > > > > This could use an explanation for why the ifdefs can be removed and why > > the alternative can be removed. > > The alternative is in the WARN_ONCE now. Ah, sneaky... It should really be called WARN_ONCE_AFTER_ALTERNATIVES or something. -- Josh
On Tue, Oct 08, 2024 at 09:45:14AM -0700, Josh Poimboeuf wrote: > On Tue, Oct 08, 2024 at 09:25:02AM +0200, Peter Zijlstra wrote: > > On Mon, Oct 07, 2024 at 10:33:45AM -0700, Josh Poimboeuf wrote: > > > On Mon, Oct 07, 2024 at 10:32:12AM +0200, Peter Zijlstra wrote: > > > > Replace the funny __warn_thunk thing with a more regular > > > > WARN_ON_ONCE(), and simplify the ifdeffery. > > > > > > > > Notably this avoids RET from having recursive RETs (once from the > > > > thunk and once from the C function) -- recursive RET makes my head > > > > hurt for no good reason. > > > > > > This could use an explanation for why the ifdefs can be removed and why > > > the alternative can be removed. > > > > The alternative is in the WARN_ONCE now. > > Ah, sneaky... It should really be called WARN_ONCE_AFTER_ALTERNATIVES or > something. Yeah, I suppose it should.
© 2016 - 2024 Red Hat, Inc.