diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-05 17:02:58 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-05 17:02:58 -0700 |
| commit | f5fdd6665ac4d8528ed1c9242cb1cf7a7f5bdb0e (patch) | |
| tree | 3a567692f23bd8837511395de260dfd923f0564f /arch/x86/kernel | |
| parent | c5096fec0c58a4f4d2475d4d88697c505800e50e (diff) | |
| parent | 7e7f81cf6f5ca3311e526308f55d7c54d3ba71f9 (diff) | |
| download | linux-next-f5fdd6665ac4d8528ed1c9242cb1cf7a7f5bdb0e.tar.gz linux-next-f5fdd6665ac4d8528ed1c9242cb1cf7a7f5bdb0e.zip | |
Merge tag 'x86_bugs_saferet' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
- Add a mitigation for the attack vector of interrupting the saferet
sequence used in the SRSO mitigation and still poisoning the RSB.
Do that by emulating the saferet sequence and thus avoiding executing
a RET instruction.
* tag 'x86_bugs_saferet' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/bugs: Make Safe-RET robust against interrupt injection
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/cpu/bugs.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index d9af230c0512..82436b3534fa 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -3775,3 +3775,42 @@ void __warn_thunk(void) { WARN_ONCE(1, "Unpatched return thunk in use. This should not happen!\n"); } + +#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 */ |
