At entry userspace may have populated the extra registers outside the
syscall calling convention with values that could be useful in a
speculative execution attack. Clear them to minimize the kernel's attack
surface. Note, this only clears the extra registers and not the unused
registers for syscalls less than 6 arguments since those registers are
likely to be clobbered well before their values could be put to use
under speculation.

Note, Linus found that the 'xor' instructions can be executed with
minimized cost if interleaved with the 'push' instructions, and Ingo's
analysis found that r10 and r11 should be included in the register
clearing beyond the typical 'extra' syscall calling convention
registers.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: "H. Peter Anvin" <h...@zytor.com>
Cc: x...@kernel.org
Cc: Andy Lutomirski <l...@kernel.org>
Suggested-by: Linus Torvalds <torva...@linux-foundation.org>
Reported-by: Andi Kleen <a...@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.willi...@intel.com>
---
 arch/x86/entry/entry_64.S |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index c752abe89d80..e8c3a902333d 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -235,13 +235,26 @@ GLOBAL(entry_SYSCALL_64_after_hwframe)
        pushq   %r8                             /* pt_regs->r8 */
        pushq   %r9                             /* pt_regs->r9 */
        pushq   %r10                            /* pt_regs->r10 */
+       /*
+        * Sanitize extra registers of values that a speculation attack
+        * might want to exploit. Interleave xor with pushq for better
+        * uop scheduling.
+        */
+       xorq    %r10, %r10                      /* nospec   r10 */
        pushq   %r11                            /* pt_regs->r11 */
+       xorq    %r11, %r11                      /* nospec   r11 */
        pushq   %rbx                            /* pt_regs->rbx */
+       xorl    %ebx, %ebx                      /* nospec   rbx */
        pushq   %rbp                            /* pt_regs->rbp */
+       xorl    %ebp, %ebp                      /* nospec   rbp */
        pushq   %r12                            /* pt_regs->r12 */
+       xorq    %r12, %r12                      /* nospec   r12 */
        pushq   %r13                            /* pt_regs->r13 */
+       xorq    %r13, %r13                      /* nospec   r13 */
        pushq   %r14                            /* pt_regs->r14 */
+       xorq    %r14, %r14                      /* nospec   r14 */
        pushq   %r15                            /* pt_regs->r15 */
+       xorq    %r15, %r15                      /* nospec   r15 */
        UNWIND_HINT_REGS
 
        TRACE_IRQS_OFF

Reply via email to