syscalls/x86: Extend register clearing on syscall entry to lower registers
authorDominik Brodowski <linux@dominikbrodowski.net>
Thu, 5 Apr 2018 09:53:06 +0000 (11:53 +0200)
committerIngo Molnar <mingo@kernel.org>
Thu, 5 Apr 2018 14:59:39 +0000 (16:59 +0200)
To reduce the chance that random user space content leaks down the call
chain in registers, also clear lower registers on syscall entry:

For 64-bit syscalls, extend the register clearing in PUSH_AND_CLEAR_REGS
to %dx and %cx. This should not hurt at all, also on the other callers
of that macro. We do not need to clear %rdi and %rsi for syscall entry,
as those registers are used to pass the parameters to do_syscall_64().

For the 32-bit compat syscalls, do_int80_syscall_32() and
do_fast_syscall_32() each only take one parameter. Therefore, extend the
register clearing to %dx, %cx, and %si in entry_SYSCALL_compat and
entry_INT80_compat.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20180405095307.3730-8-linux@dominikbrodowski.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/entry/calling.h
arch/x86/entry/entry_64_compat.S

index be63330c551129cb6bf0fcf07d8bf6d4600cb098..352e70cd33e80b99186e892b4080dfe481ad5dc4 100644 (file)
@@ -114,7 +114,9 @@ For 32-bit we have the following conventions - kernel is built with
        pushq   %rsi            /* pt_regs->si */
        .endif
        pushq   \rdx            /* pt_regs->dx */
+       xorl    %edx, %edx      /* nospec   dx */
        pushq   %rcx            /* pt_regs->cx */
+       xorl    %ecx, %ecx      /* nospec   cx */
        pushq   \rax            /* pt_regs->ax */
        pushq   %r8             /* pt_regs->r8 */
        xorl    %r8d, %r8d      /* nospec   r8 */
index 08425c42f8b7c726e0daa70bb4e112582a513c20..9af927e59d49745757dd1bf07ad148df0db5a006 100644 (file)
@@ -220,8 +220,11 @@ GLOBAL(entry_SYSCALL_compat_after_hwframe)
        pushq   %rax                    /* pt_regs->orig_ax */
        pushq   %rdi                    /* pt_regs->di */
        pushq   %rsi                    /* pt_regs->si */
+       xorl    %esi, %esi              /* nospec   si */
        pushq   %rdx                    /* pt_regs->dx */
+       xorl    %edx, %edx              /* nospec   dx */
        pushq   %rbp                    /* pt_regs->cx (stashed in bp) */
+       xorl    %ecx, %ecx              /* nospec   cx */
        pushq   $-ENOSYS                /* pt_regs->ax */
        pushq   $0                      /* pt_regs->r8  = 0 */
        xorl    %r8d, %r8d              /* nospec   r8 */
@@ -365,8 +368,11 @@ ENTRY(entry_INT80_compat)
 
        pushq   (%rdi)                  /* pt_regs->di */
        pushq   %rsi                    /* pt_regs->si */
+       xorl    %esi, %esi              /* nospec   si */
        pushq   %rdx                    /* pt_regs->dx */
+       xorl    %edx, %edx              /* nospec   dx */
        pushq   %rcx                    /* pt_regs->cx */
+       xorl    %ecx, %ecx              /* nospec   cx */
        pushq   $-ENOSYS                /* pt_regs->ax */
        pushq   $0                      /* pt_regs->r8  = 0 */
        xorl    %r8d, %r8d              /* nospec   r8 */