diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2018-05-11 06:16:22 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2018-05-31 18:27:26 -0400 |
commit | 10573ae547c85b2c61417ff1a106cffbfceada35 (patch) | |
tree | dbc21a6b8a94eaa26fdc73b4440affa5ad082e4c | |
parent | 1d4238c56f9816ce0f9c8dbe42d7f2ad81cb6613 (diff) |
ARM: spectre-v1: fix syscall entry
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>
-rw-r--r-- | arch/arm/kernel/entry-common.S | 18 | ||||
-rw-r--r-- | arch/arm/kernel/entry-header.S | 25 |
2 files changed, 32 insertions, 11 deletions
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 3c4f88701f22..20df608bf343 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -242,9 +242,7 @@ local_restart: | |||
242 | tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? | 242 | tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? |
243 | bne __sys_trace | 243 | bne __sys_trace |
244 | 244 | ||
245 | cmp scno, #NR_syscalls @ check upper syscall limit | 245 | invoke_syscall tbl, scno, r10, ret_fast_syscall |
246 | badr lr, ret_fast_syscall @ return address | ||
247 | ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine | ||
248 | 246 | ||
249 | add r1, sp, #S_OFF | 247 | add r1, sp, #S_OFF |
250 | 2: cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) | 248 | 2: cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) |
@@ -278,14 +276,8 @@ __sys_trace: | |||
278 | mov r1, scno | 276 | mov r1, scno |
279 | add r0, sp, #S_OFF | 277 | add r0, sp, #S_OFF |
280 | bl syscall_trace_enter | 278 | bl syscall_trace_enter |
281 | 279 | mov scno, r0 | |
282 | badr lr, __sys_trace_return @ return address | 280 | invoke_syscall tbl, scno, r10, __sys_trace_return, reload=1 |
283 | mov scno, r0 @ syscall number (possibly new) | ||
284 | add r1, sp, #S_R0 + S_OFF @ pointer to regs | ||
285 | cmp scno, #NR_syscalls @ check upper syscall limit | ||
286 | ldmccia r1, {r0 - r6} @ have to reload r0 - r6 | ||
287 | stmccia sp, {r4, r5} @ and update the stack args | ||
288 | ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine | ||
289 | cmp scno, #-1 @ skip the syscall? | 281 | cmp scno, #-1 @ skip the syscall? |
290 | bne 2b | 282 | bne 2b |
291 | add sp, sp, #S_OFF @ restore stack | 283 | add sp, sp, #S_OFF @ restore stack |
@@ -363,6 +355,10 @@ sys_syscall: | |||
363 | bic scno, r0, #__NR_OABI_SYSCALL_BASE | 355 | bic scno, r0, #__NR_OABI_SYSCALL_BASE |
364 | cmp scno, #__NR_syscall - __NR_SYSCALL_BASE | 356 | cmp scno, #__NR_syscall - __NR_SYSCALL_BASE |
365 | cmpne scno, #NR_syscalls @ check range | 357 | cmpne scno, #NR_syscalls @ check range |
358 | #ifdef CONFIG_CPU_SPECTRE | ||
359 | movhs scno, #0 | ||
360 | csdb | ||
361 | #endif | ||
366 | stmloia sp, {r5, r6} @ shuffle args | 362 | stmloia sp, {r5, r6} @ shuffle args |
367 | movlo r0, r1 | 363 | movlo r0, r1 |
368 | movlo r1, r2 | 364 | movlo r1, r2 |
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 0f07579af472..773424843d6e 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S | |||
@@ -378,6 +378,31 @@ | |||
378 | #endif | 378 | #endif |
379 | .endm | 379 | .endm |
380 | 380 | ||
381 | .macro invoke_syscall, table, nr, tmp, ret, reload=0 | ||
382 | #ifdef CONFIG_CPU_SPECTRE | ||
383 | mov \tmp, \nr | ||
384 | cmp \tmp, #NR_syscalls @ check upper syscall limit | ||
385 | movcs \tmp, #0 | ||
386 | csdb | ||
387 | badr lr, \ret @ return address | ||
388 | .if \reload | ||
389 | add r1, sp, #S_R0 + S_OFF @ pointer to regs | ||
390 | ldmccia r1, {r0 - r6} @ reload r0-r6 | ||
391 | stmccia sp, {r4, r5} @ update stack arguments | ||
392 | .endif | ||
393 | ldrcc pc, [\table, \tmp, lsl #2] @ call sys_* routine | ||
394 | #else | ||
395 | cmp \nr, #NR_syscalls @ check upper syscall limit | ||
396 | badr lr, \ret @ return address | ||
397 | .if \reload | ||
398 | add r1, sp, #S_R0 + S_OFF @ pointer to regs | ||
399 | ldmccia r1, {r0 - r6} @ reload r0-r6 | ||
400 | stmccia sp, {r4, r5} @ update stack arguments | ||
401 | .endif | ||
402 | ldrcc pc, [\table, \nr, lsl #2] @ call sys_* routine | ||
403 | #endif | ||
404 | .endm | ||
405 | |||
381 | /* | 406 | /* |
382 | * These are the registers used in the syscall handler, and allow us to | 407 | * These are the registers used in the syscall handler, and allow us to |
383 | * have in theory up to 7 arguments to a function - r0 to r6. | 408 | * have in theory up to 7 arguments to a function - r0 to r6. |