On Mon, 2022-08-29 at 10:30 +0200, gregkh@xxxxxxxxxxxxxxxxxxx wrote: > The patch below does not apply to the 5.10-stable tree. > If someone wants it applied there, or to any other stable or longterm > tree, then please email the backport, including the original git commit > id to <stable@xxxxxxxxxxxxxxx>. > You need commit 4e3aa9238277 "x86/nospec: Unwreck the RSB stuffing" before this one. I've attached the backport of that for 5.10. I haven't checked the older branches. Ben. > thanks, > > greg k-h > > ------------------ original commit in Linus's tree ------------------ > > From 332924973725e8cdcc783c175f68cf7e162cb9e5 Mon Sep 17 00:00:00 2001 > From: Peter Zijlstra <peterz@xxxxxxxxxxxxx> > Date: Fri, 19 Aug 2022 13:01:35 +0200 > Subject: [PATCH] x86/nospec: Fix i386 RSB stuffing > > Turns out that i386 doesn't unconditionally have LFENCE, as such the > loop in __FILL_RETURN_BUFFER isn't actually speculation safe on such > chips. > > Fixes: ba6e31af2be9 ("x86/speculation: Add LFENCE to RSB fill sequence") > Reported-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> > Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx> > Link: https://lkml.kernel.org/r/Yv9tj9vbQ9nNlXoY@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx > > diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h > index 10731ccfed37..c936ce9f0c47 100644 > --- a/arch/x86/include/asm/nospec-branch.h > +++ b/arch/x86/include/asm/nospec-branch.h > @@ -50,6 +50,7 @@ > * the optimal version - two calls, each with their own speculation > * trap should their return address end up getting used, in a loop. > */ > +#ifdef CONFIG_X86_64 > #define __FILL_RETURN_BUFFER(reg, nr) \ > mov $(nr/2), reg; \ > 771: \ > @@ -60,6 +61,17 @@ > jnz 771b; \ > /* barrier for jnz misprediction */ \ > lfence; > +#else > +/* > + * i386 doesn't unconditionally have LFENCE, as such it can't > + * do a loop. > + */ > +#define __FILL_RETURN_BUFFER(reg, nr) \ > + .rept nr; \ > + __FILL_RETURN_SLOT; \ > + .endr; \ > + add $(BITS_PER_LONG/8) * nr, %_ASM_SP; > +#endif > > /* > * Stuff a single RSB slot. > -- Ben Hutchings Make three consecutive correct guesses and you will be considered an expert.
From: Peter Zijlstra <peterz@xxxxxxxxxxxxx> Date: Tue, 16 Aug 2022 14:28:36 +0200 Subject: x86/nospec: Unwreck the RSB stuffing commit 4e3aa9238277597c6c7624f302d81a7b568b6f2d upstream. Commit 2b1299322016 ("x86/speculation: Add RSB VM Exit protections") made a right mess of the RSB stuffing, rewrite the whole thing to not suck. Thanks to Andrew for the enlightening comment about Post-Barrier RSB things so we can make this code less magical. Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx> Link: https://lkml.kernel.org/r/YvuNdDWoUZSBjYcm@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [bwh: Backported to 5.10: adjust context] Signed-off-by: Ben Hutchings <benh@xxxxxxxxxx> --- arch/x86/include/asm/nospec-branch.h | 80 ++++++++++++++-------------- 1 file changed, 39 insertions(+), 41 deletions(-) --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -35,33 +35,44 @@ #define RSB_CLEAR_LOOPS 32 /* To forcibly overwrite all entries */ /* + * Common helper for __FILL_RETURN_BUFFER and __FILL_ONE_RETURN. + */ +#define __FILL_RETURN_SLOT \ + ANNOTATE_INTRA_FUNCTION_CALL; \ + call 772f; \ + int3; \ +772: + +/* + * Stuff the entire RSB. + * * Google experimented with loop-unrolling and this turned out to be * the optimal version — two calls, each with their own speculation * trap should their return address end up getting used, in a loop. */ -#define __FILL_RETURN_BUFFER(reg, nr, sp) \ - mov $(nr/2), reg; \ -771: \ - ANNOTATE_INTRA_FUNCTION_CALL; \ - call 772f; \ -773: /* speculation trap */ \ - UNWIND_HINT_EMPTY; \ - pause; \ - lfence; \ - jmp 773b; \ -772: \ - ANNOTATE_INTRA_FUNCTION_CALL; \ - call 774f; \ -775: /* speculation trap */ \ - UNWIND_HINT_EMPTY; \ - pause; \ - lfence; \ - jmp 775b; \ -774: \ - add $(BITS_PER_LONG/8) * 2, sp; \ - dec reg; \ - jnz 771b; \ - /* barrier for jnz misprediction */ \ +#define __FILL_RETURN_BUFFER(reg, nr) \ + mov $(nr/2), reg; \ +771: \ + __FILL_RETURN_SLOT \ + __FILL_RETURN_SLOT \ + add $(BITS_PER_LONG/8) * 2, %_ASM_SP; \ + dec reg; \ + jnz 771b; \ + /* barrier for jnz misprediction */ \ + lfence; + +/* + * Stuff a single RSB slot. + * + * To mitigate Post-Barrier RSB speculation, one CALL instruction must be + * forced to retire before letting a RET instruction execute. + * + * On PBRSB-vulnerable CPUs, it is not safe for a RET to be executed + * before this point. + */ +#define __FILL_ONE_RETURN \ + __FILL_RETURN_SLOT \ + add $(BITS_PER_LONG/8), %_ASM_SP; \ lfence; #ifdef __ASSEMBLY__ @@ -120,28 +131,15 @@ #endif .endm -.macro ISSUE_UNBALANCED_RET_GUARD - ANNOTATE_INTRA_FUNCTION_CALL - call .Lunbalanced_ret_guard_\@ - int3 -.Lunbalanced_ret_guard_\@: - add $(BITS_PER_LONG/8), %_ASM_SP - lfence -.endm - /* * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP * monstrosity above, manually. */ -.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2 -.ifb \ftr2 - ALTERNATIVE "jmp .Lskip_rsb_\@", "", \ftr -.else - ALTERNATIVE_2 "jmp .Lskip_rsb_\@", "", \ftr, "jmp .Lunbalanced_\@", \ftr2 -.endif - __FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP) -.Lunbalanced_\@: - ISSUE_UNBALANCED_RET_GUARD +.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2=ALT_NOT(X86_FEATURE_ALWAYS) + ALTERNATIVE_2 "jmp .Lskip_rsb_\@", \ + __stringify(__FILL_RETURN_BUFFER(\reg,\nr)), \ftr, \ + __stringify(__FILL_ONE_RETURN), \ftr2 + .Lskip_rsb_\@: .endm
Attachment:
signature.asc
Description: This is a digitally signed message part