From: Greg Kroah-Hartman Date: Thu, 6 Aug 2026 17:18:01 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v5.10.263~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1459f5cb5f543118df14d0b5d5bb8c042d497ed;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: saferet-5.10.262-x86-bugs-Make-Safe-RET-robust-against-interrupt-inje.patch series --- diff --git a/queue-5.10/saferet-5.10.262-x86-bugs-Make-Safe-RET-robust-against-interrupt-inje.patch b/queue-5.10/saferet-5.10.262-x86-bugs-Make-Safe-RET-robust-against-interrupt-inje.patch new file mode 100644 index 0000000000..4be23e4b4e --- /dev/null +++ b/queue-5.10/saferet-5.10.262-x86-bugs-Make-Safe-RET-robust-against-interrupt-inje.patch @@ -0,0 +1,215 @@ +From b316bd3db2f2b3b441dcdfce0b05f0394c278aed Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Tue, 2 Jun 2026 21:26:44 -0700 +Subject: x86/bugs: Make Safe-RET robust against interrupt injection + +From: "Borislav Petkov (AMD)" + +commit 7e7f81cf6f5ca3311e526308f55d7c54d3ba71f9 upstream. + +An attacker injecting interrupts while the Safe-RET mitigation executes +on machines affected by SRSO can neutralize the safe return sequence, +potentially leading to data leakage through speculative execution. + +Fixup register state as if the Safe-RET sequence executed successfully +by "emulating" it, in a manner of speaking, and avoid executing a RET +instruction after returning from the interrupt. + +Co-developed-by: David Kaplan +Signed-off-by: David Kaplan +Signed-off-by: Borislav Petkov (AMD) +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/entry/entry_64.S | 5 +++ + arch/x86/include/asm/nospec-branch.h | 56 +++++++++++++++++++++++++++++++++++ + arch/x86/kernel/cpu/bugs.c | 39 ++++++++++++++++++++++++ + arch/x86/lib/retpoline.S | 20 ++++++++++++ + 4 files changed, 120 insertions(+) + +--- a/arch/x86/entry/entry_64.S ++++ b/arch/x86/entry/entry_64.S +@@ -971,6 +971,8 @@ SYM_CODE_START_LOCAL(paranoid_entry) + IBRS_ENTER save_reg=%r15 + UNTRAIN_RET + ++ HANDLE_INTR_SAFERET 8(%rsp) ++ + RET + SYM_CODE_END(paranoid_entry) + +@@ -1078,6 +1080,9 @@ SYM_CODE_START_LOCAL(error_entry) + movl %ecx, %eax /* zero extend */ + cmpq %rax, RIP+8(%rsp) + je .Lbstep_iret ++ ++ HANDLE_INTR_SAFERET 8(%rsp) ++ + cmpq $.Lgs_change, RIP+8(%rsp) + jne .Lerror_entry_done_lfence + +--- a/arch/x86/include/asm/nospec-branch.h ++++ b/arch/x86/include/asm/nospec-branch.h +@@ -87,6 +87,50 @@ + add $(BITS_PER_LONG/8), %_ASM_SP; \ + lfence; + ++/* ++ * Helper for detecting if an interrupt occurred at an unsafe location within ++ * Safe-RET. If Safe-RET is interrupted after the CALL or LEA the RSB may get ++ * poisoned by the interrupt handler. ++ * ++ * The Safe-RET sequence is: ++ * ++ * CALL ++ * LEA 8(%RSP), %RSP ++ * RET ++ * ++ * The two CMPs below check whether RIP points to after the CALL or after the ++ * LEA. ++ * ++ * The LFENCE below is to address this particular speculation case: ++ * ++ * 1. Userspace runs and poisons the BTB around the safe-RET routine ++ * ++ * 2. Userspace triggers some kind of exception ++ * ++ * 3. Kernel executes error_entry() and mis-speculates the branch into thinking ++ * it actually came from kernel space ++ * ++ * 4. The kernel then further mis-speculates that the exception occurred due ++ * to an interrupted safe-RET ++ * ++ * 5. The handle_interrupted_saferet() routine speculatively executes and ++ * speculatively does a safe-RET. But this is unsafe since it was never ++ * untrained. ++ * ++ * The LFENCE fixes this by ensuring step 5 is never reached speculatively. ++ * Note that this LFENCE only occurs if safe-RET was actually interrupted (so ++ * it's outside of the normal path). ++ */ ++#define __HANDLE_INTR_SAFERET(name, pt_regs) \ ++ cmpq $(name), RIP+pt_regs; \ ++ jb 1f; \ ++ cmpq $(name)+5, RIP+pt_regs; \ ++ ja 1f; \ ++ lfence; \ ++ leaq pt_regs, %rdi; \ ++ call handle_interrupted_saferet; \ ++ 1: ++ + #ifdef __ASSEMBLY__ + + /* +@@ -190,6 +234,14 @@ + #endif + .endm + ++.macro HANDLE_INTR_SAFERET pt_regs ++#ifdef CONFIG_MITIGATION_SRSO ++ ALTERNATIVE_2 "", \ ++ __stringify(__HANDLE_INTR_SAFERET(srso_safe_ret, \pt_regs)), X86_FEATURE_SRSO, \ ++ __stringify(__HANDLE_INTR_SAFERET(srso_alias_safe_ret, \pt_regs)), X86_FEATURE_SRSO_ALIAS ++#endif ++.endm ++ + /* + * Macro to execute VERW insns that mitigate transient data sampling + * attacks such as MDS or TSA. On affected systems a microcode update +@@ -449,6 +501,10 @@ static __always_inline void x86_idle_cle + x86_clear_cpu_buffers(); + } + ++void srso_safe_ret(void); ++void srso_alias_safe_ret(void); ++void handle_interrupted_saferet(struct pt_regs *regs); ++ + #endif /* __ASSEMBLY__ */ + + #endif /* _ASM_X86_NOSPEC_BRANCH_H_ */ +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -3238,3 +3238,42 @@ ssize_t cpu_show_vmscape(struct device * + return cpu_show_common(dev, attr, buf, X86_BUG_VMSCAPE); + } + #endif ++ ++#ifdef CONFIG_MITIGATION_SRSO ++/* ++ * Called during exception/interrupt entry if interrupted during the ++ * safe-RET sequence. The safe-RET sequence consists of 3 instructions: ++ * ++ * CALL ++ * LEA 8(%RSP), %RSP ++ * RET ++ * ++ * An interrupt after the CALL or after the LEA could potentially lead ++ * to branch predictor poisoning and results in the sequence not being ++ * able to be safely resumed. ++ * ++ * Therefore, modify the regs state as if the remaining part of the ++ * safe-RET sequence executed so the interrupt returns back to the ++ * desired return target, instead of the to the safe-RET sequence. ++ */ ++void noinstr handle_interrupted_saferet(struct pt_regs *regs) ++{ ++ unsigned long rip = regs->ip; ++ ++ if (rip == (unsigned long) srso_safe_ret || ++ rip == (unsigned long) srso_alias_safe_ret) { ++ /* Modify stack pointer as if LEA executed: */ ++ regs->sp += 8; ++ } ++ ++ /* ++ * Adjust registers as if RET executed: ++ * ++ * 1. Read the return address off the stack and into rIP: ++ */ ++ regs->ip = *(unsigned long *)(regs->sp); ++ ++ /* 2. Pop rIP off the stack: */ ++ regs->sp += 8; ++} ++#endif /* CONFIG_MITIGATION_SRSO */ +--- a/arch/x86/lib/retpoline.S ++++ b/arch/x86/lib/retpoline.S +@@ -113,10 +113,24 @@ __EXPORT_THUNK(srso_alias_untrain_ret) + #endif + + SYM_START(srso_alias_safe_ret, SYM_L_GLOBAL, SYM_A_NONE) ++ ++ /* ++ * Tell objtool that those are not function pointers referenced by ++ * __HANDLE_INTR_SAFERET(). Below too. ++ */ ++ ANNOTATE_NOENDBR ++ ++ /* ++ * Safe-RET sequence. If you need to change it, adjust ++ * handle_interrupted_saferet() too. ++ */ + lea 8(%_ASM_SP), %_ASM_SP + UNWIND_HINT_FUNC ++ ++ ANNOTATE_NOENDBR + ANNOTATE_UNRET_SAFE + ret ++ /* End of Safe-RET sequence */ + int3 + SYM_FUNC_END(srso_alias_safe_ret) + +@@ -231,8 +245,14 @@ SYM_START(srso_untrain_ret, SYM_L_GLOBAL + * the stack. + */ + SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL) ++ /* ++ * Safe-RET sequence. If you need to change it, adjust ++ * handle_interrupted_saferet() too. ++ */ + lea 8(%_ASM_SP), %_ASM_SP + ret ++ /* End of Safe-RET sequence */ ++ + int3 + int3 + /* end of movabs */ diff --git a/queue-5.10/series b/queue-5.10/series new file mode 100644 index 0000000000..c744c764dc --- /dev/null +++ b/queue-5.10/series @@ -0,0 +1 @@ +saferet-5.10.262-x86-bugs-Make-Safe-RET-robust-against-interrupt-inje.patch