Commit 5324b252 authored by Jiri Slaby's avatar Jiri Slaby Committed by Stefan Bader

x86/syscall: Sanitize syscall table de-references under speculation fix

BugLink: https://bugs.launchpad.net/bugs/1774181

In 4.4.118, we have commit c8961332 (x86/syscall: Sanitize syscall
table de-references under speculation), which is a backport of upstream
commit 2fbd7af5. But it fixed only the C part of the upstream patch
-- the IA32 sysentry. So it ommitted completely the assembly part -- the
64bit sysentry.

Fix that in this patch by explicit array_index_mask_nospec written in
assembly. The same was used in lib/getuser.S.

However, to have "sbb" working properly, we have to switch from "cmp"
against (NR_syscalls-1) to (NR_syscalls), otherwise the last syscall
number would be "and"ed by 0. It is because the original "ja" relies on
"CF" or "ZF", but we rely only on "CF" in "sbb". That means: switch to
"jae" conditional jump too.

Final note: use rcx for mask as this is exactly what is overwritten by
the 4th syscall argument (r10) right after.
Reported-by: default avatarJan Beulich <JBeulich@suse.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Andy Lutomirski <luto@kernel.org>
Cc: alan@linux.intel.com
Cc: Jinpu Wang <jinpu.wang@profitbricks.com>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 5fed0b35 linux-4.4.y)
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
Acked-by: default avatarStefan Bader <stefan.bader@canonical.com>
Acked-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
parent 18c7cf72
...@@ -181,12 +181,14 @@ GLOBAL(entry_SYSCALL_64_after_swapgs) ...@@ -181,12 +181,14 @@ GLOBAL(entry_SYSCALL_64_after_swapgs)
jnz tracesys jnz tracesys
entry_SYSCALL_64_fastpath: entry_SYSCALL_64_fastpath:
#if __SYSCALL_MASK == ~0 #if __SYSCALL_MASK == ~0
cmpq $__NR_syscall_max, %rax cmpq $NR_syscalls, %rax
#else #else
andl $__SYSCALL_MASK, %eax andl $__SYSCALL_MASK, %eax
cmpl $__NR_syscall_max, %eax cmpl $NR_syscalls, %eax
#endif #endif
ja 1f /* return -ENOSYS (already in pt_regs->ax) */ jae 1f /* return -ENOSYS (already in pt_regs->ax) */
sbb %rcx, %rcx /* array_index_mask_nospec() */
and %rcx, %rax
movq %r10, %rcx movq %r10, %rcx
#ifdef CONFIG_RETPOLINE #ifdef CONFIG_RETPOLINE
movq sys_call_table(, %rax, 8), %rax movq sys_call_table(, %rax, 8), %rax
...@@ -282,12 +284,14 @@ tracesys_phase2: ...@@ -282,12 +284,14 @@ tracesys_phase2:
RESTORE_C_REGS_EXCEPT_RAX RESTORE_C_REGS_EXCEPT_RAX
RESTORE_EXTRA_REGS RESTORE_EXTRA_REGS
#if __SYSCALL_MASK == ~0 #if __SYSCALL_MASK == ~0
cmpq $__NR_syscall_max, %rax cmpq $NR_syscalls, %rax
#else #else
andl $__SYSCALL_MASK, %eax andl $__SYSCALL_MASK, %eax
cmpl $__NR_syscall_max, %eax cmpl $NR_syscalls, %eax
#endif #endif
ja 1f /* return -ENOSYS (already in pt_regs->ax) */ jae 1f /* return -ENOSYS (already in pt_regs->ax) */
sbb %rcx, %rcx /* array_index_mask_nospec() */
and %rcx, %rax
movq %r10, %rcx /* fixup for C */ movq %r10, %rcx /* fixup for C */
#ifdef CONFIG_RETPOLINE #ifdef CONFIG_RETPOLINE
movq sys_call_table(, %rax, 8), %rax movq sys_call_table(, %rax, 8), %rax
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment