| From foo@baz Wed Nov 21 19:20:53 CET 2018 |
| From: David Long <dave.long@linaro.org> |
| Date: Wed, 7 Nov 2018 11:43:56 -0500 |
| Subject: ARM: spectre-v1: fix syscall entry |
| To: stable@vger.kernel.org, Russell King - ARM Linux <linux@armlinux.org.uk>, Florian Fainelli <f.fainelli@gmail.com>, Tony Lindgren <tony@atomide.com>, Marc Zyngier <marc.zyngier@arm.com>, Mark Rutland <mark.rutland@arm.com> |
| Cc: Greg KH <gregkh@linuxfoundation.org>, Mark Brown <broonie@kernel.org> |
| Message-ID: <20181107164402.9380-19-dave.long@linaro.org> |
| |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| |
| Commit 10573ae547c85b2c61417ff1a106cffbfceada35 upstream. |
| |
| Prevent speculation at the syscall table decoding by clamping the index |
| used to zero on invalid system call numbers, and using the csdb |
| speculative barrier. |
| |
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| Acked-by: Mark Rutland <mark.rutland@arm.com> |
| Boot-tested-by: Tony Lindgren <tony@atomide.com> |
| Reviewed-by: Tony Lindgren <tony@atomide.com> |
| Signed-off-by: David A. Long <dave.long@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/arm/kernel/entry-common.S | 18 +++++++----------- |
| arch/arm/kernel/entry-header.S | 25 +++++++++++++++++++++++++ |
| 2 files changed, 32 insertions(+), 11 deletions(-) |
| |
| --- a/arch/arm/kernel/entry-common.S |
| +++ b/arch/arm/kernel/entry-common.S |
| @@ -223,9 +223,7 @@ local_restart: |
| tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? |
| bne __sys_trace |
| |
| - cmp scno, #NR_syscalls @ check upper syscall limit |
| - badr lr, ret_fast_syscall @ return address |
| - ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine |
| + invoke_syscall tbl, scno, r10, ret_fast_syscall |
| |
| add r1, sp, #S_OFF |
| 2: cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) |
| @@ -258,14 +256,8 @@ __sys_trace: |
| mov r1, scno |
| add r0, sp, #S_OFF |
| bl syscall_trace_enter |
| - |
| - badr lr, __sys_trace_return @ return address |
| - mov scno, r0 @ syscall number (possibly new) |
| - add r1, sp, #S_R0 + S_OFF @ pointer to regs |
| - cmp scno, #NR_syscalls @ check upper syscall limit |
| - ldmccia r1, {r0 - r6} @ have to reload r0 - r6 |
| - stmccia sp, {r4, r5} @ and update the stack args |
| - ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine |
| + mov scno, r0 |
| + invoke_syscall tbl, scno, r10, __sys_trace_return, reload=1 |
| cmp scno, #-1 @ skip the syscall? |
| bne 2b |
| add sp, sp, #S_OFF @ restore stack |
| @@ -317,6 +309,10 @@ sys_syscall: |
| bic scno, r0, #__NR_OABI_SYSCALL_BASE |
| cmp scno, #__NR_syscall - __NR_SYSCALL_BASE |
| cmpne scno, #NR_syscalls @ check range |
| +#ifdef CONFIG_CPU_SPECTRE |
| + movhs scno, #0 |
| + csdb |
| +#endif |
| stmloia sp, {r5, r6} @ shuffle args |
| movlo r0, r1 |
| movlo r1, r2 |
| --- a/arch/arm/kernel/entry-header.S |
| +++ b/arch/arm/kernel/entry-header.S |
| @@ -377,6 +377,31 @@ |
| #endif |
| .endm |
| |
| + .macro invoke_syscall, table, nr, tmp, ret, reload=0 |
| +#ifdef CONFIG_CPU_SPECTRE |
| + mov \tmp, \nr |
| + cmp \tmp, #NR_syscalls @ check upper syscall limit |
| + movcs \tmp, #0 |
| + csdb |
| + badr lr, \ret @ return address |
| + .if \reload |
| + add r1, sp, #S_R0 + S_OFF @ pointer to regs |
| + ldmccia r1, {r0 - r6} @ reload r0-r6 |
| + stmccia sp, {r4, r5} @ update stack arguments |
| + .endif |
| + ldrcc pc, [\table, \tmp, lsl #2] @ call sys_* routine |
| +#else |
| + cmp \nr, #NR_syscalls @ check upper syscall limit |
| + badr lr, \ret @ return address |
| + .if \reload |
| + add r1, sp, #S_R0 + S_OFF @ pointer to regs |
| + ldmccia r1, {r0 - r6} @ reload r0-r6 |
| + stmccia sp, {r4, r5} @ update stack arguments |
| + .endif |
| + ldrcc pc, [\table, \nr, lsl #2] @ call sys_* routine |
| +#endif |
| + .endm |
| + |
| /* |
| * These are the registers used in the syscall handler, and allow us to |
| * have in theory up to 7 arguments to a function - r0 to r6. |