aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2017-11-24 18:49:34 -0500
committerRussell King <rmk+kernel@armlinux.org.uk>2017-11-26 10:41:39 -0500
commit8bafae202c82dc257f649ea3c275a0f35ee15113 (patch)
tree1c2a7d64f216df552e4509dc746d8da3436e39ab
parent400eeffaffc7232c0ae1134fe04e14ae4fb48d8c (diff)
ARM: BUG if jumping to usermode address in kernel mode
Detect if we are returning to usermode via the normal kernel exit paths but the saved PSR value indicates that we are in kernel mode. This could occur due to corrupted stack state, which has been observed with "ftracetest". This ensures that we catch the problem case before we get to user code. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--arch/arm/include/asm/assembler.h18
-rw-r--r--arch/arm/kernel/entry-header.S6
2 files changed, 24 insertions, 0 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index ad301f107dd2..bc8d4bbd82e2 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -518,4 +518,22 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
518#endif 518#endif
519 .endm 519 .endm
520 520
521 .macro bug, msg, line
522#ifdef CONFIG_THUMB2_KERNEL
5231: .inst 0xde02
524#else
5251: .inst 0xe7f001f2
526#endif
527#ifdef CONFIG_DEBUG_BUGVERBOSE
528 .pushsection .rodata.str, "aMS", %progbits, 1
5292: .asciz "\msg"
530 .popsection
531 .pushsection __bug_table, "aw"
532 .align 2
533 .word 1b, 2b
534 .hword \line
535 .popsection
536#endif
537 .endm
538
521#endif /* __ASM_ASSEMBLER_H__ */ 539#endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 6391728c8f03..75f7a4e8541a 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -299,6 +299,8 @@
299 mov r2, sp 299 mov r2, sp
300 ldr r1, [r2, #\offset + S_PSR] @ get calling cpsr 300 ldr r1, [r2, #\offset + S_PSR] @ get calling cpsr
301 ldr lr, [r2, #\offset + S_PC]! @ get pc 301 ldr lr, [r2, #\offset + S_PC]! @ get pc
302 tst r1, #0xcf
303 bne 1f
302 msr spsr_cxsf, r1 @ save in spsr_svc 304 msr spsr_cxsf, r1 @ save in spsr_svc
303#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) 305#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
304 @ We must avoid clrex due to Cortex-A15 erratum #830321 306 @ We must avoid clrex due to Cortex-A15 erratum #830321
@@ -313,6 +315,7 @@
313 @ after ldm {}^ 315 @ after ldm {}^
314 add sp, sp, #\offset + PT_REGS_SIZE 316 add sp, sp, #\offset + PT_REGS_SIZE
315 movs pc, lr @ return & move spsr_svc into cpsr 317 movs pc, lr @ return & move spsr_svc into cpsr
3181: bug "Returning to usermode but unexpected PSR bits set?", \@
316#elif defined(CONFIG_CPU_V7M) 319#elif defined(CONFIG_CPU_V7M)
317 @ V7M restore. 320 @ V7M restore.
318 @ Note that we don't need to do clrex here as clearing the local 321 @ Note that we don't need to do clrex here as clearing the local
@@ -328,6 +331,8 @@
328 ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr 331 ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
329 ldr lr, [sp, #\offset + S_PC] @ get pc 332 ldr lr, [sp, #\offset + S_PC] @ get pc
330 add sp, sp, #\offset + S_SP 333 add sp, sp, #\offset + S_SP
334 tst r1, #0xcf
335 bne 1f
331 msr spsr_cxsf, r1 @ save in spsr_svc 336 msr spsr_cxsf, r1 @ save in spsr_svc
332 337
333 @ We must avoid clrex due to Cortex-A15 erratum #830321 338 @ We must avoid clrex due to Cortex-A15 erratum #830321
@@ -340,6 +345,7 @@
340 .endif 345 .endif
341 add sp, sp, #PT_REGS_SIZE - S_SP 346 add sp, sp, #PT_REGS_SIZE - S_SP
342 movs pc, lr @ return & move spsr_svc into cpsr 347 movs pc, lr @ return & move spsr_svc into cpsr
3481: bug "Returning to usermode but unexpected PSR bits set?", \@
343#endif /* !CONFIG_THUMB2_KERNEL */ 349#endif /* !CONFIG_THUMB2_KERNEL */
344 .endm 350 .endm
345 351