Commit 8bafae20 authored by Russell King's avatar Russell King

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: default avatarRussell King <rmk+kernel@armlinux.org.uk>
parent 400eeffa
...@@ -518,4 +518,22 @@ THUMB( orr \reg , \reg , #PSR_T_BIT ) ...@@ -518,4 +518,22 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
#endif #endif
.endm .endm
.macro bug, msg, line
#ifdef CONFIG_THUMB2_KERNEL
1: .inst 0xde02
#else
1: .inst 0xe7f001f2
#endif
#ifdef CONFIG_DEBUG_BUGVERBOSE
.pushsection .rodata.str, "aMS", %progbits, 1
2: .asciz "\msg"
.popsection
.pushsection __bug_table, "aw"
.align 2
.word 1b, 2b
.hword \line
.popsection
#endif
.endm
#endif /* __ASM_ASSEMBLER_H__ */ #endif /* __ASM_ASSEMBLER_H__ */
...@@ -299,6 +299,8 @@ ...@@ -299,6 +299,8 @@
mov r2, sp mov r2, sp
ldr r1, [r2, #\offset + S_PSR] @ get calling cpsr ldr r1, [r2, #\offset + S_PSR] @ get calling cpsr
ldr lr, [r2, #\offset + S_PC]! @ get pc ldr lr, [r2, #\offset + S_PC]! @ get pc
tst r1, #0xcf
bne 1f
msr spsr_cxsf, r1 @ save in spsr_svc msr spsr_cxsf, r1 @ save in spsr_svc
#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K) #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
@ We must avoid clrex due to Cortex-A15 erratum #830321 @ We must avoid clrex due to Cortex-A15 erratum #830321
...@@ -313,6 +315,7 @@ ...@@ -313,6 +315,7 @@
@ after ldm {}^ @ after ldm {}^
add sp, sp, #\offset + PT_REGS_SIZE add sp, sp, #\offset + PT_REGS_SIZE
movs pc, lr @ return & move spsr_svc into cpsr movs pc, lr @ return & move spsr_svc into cpsr
1: bug "Returning to usermode but unexpected PSR bits set?", \@
#elif defined(CONFIG_CPU_V7M) #elif defined(CONFIG_CPU_V7M)
@ V7M restore. @ V7M restore.
@ Note that we don't need to do clrex here as clearing the local @ Note that we don't need to do clrex here as clearing the local
...@@ -328,6 +331,8 @@ ...@@ -328,6 +331,8 @@
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
ldr lr, [sp, #\offset + S_PC] @ get pc ldr lr, [sp, #\offset + S_PC] @ get pc
add sp, sp, #\offset + S_SP add sp, sp, #\offset + S_SP
tst r1, #0xcf
bne 1f
msr spsr_cxsf, r1 @ save in spsr_svc msr spsr_cxsf, r1 @ save in spsr_svc
@ We must avoid clrex due to Cortex-A15 erratum #830321 @ We must avoid clrex due to Cortex-A15 erratum #830321
...@@ -340,6 +345,7 @@ ...@@ -340,6 +345,7 @@
.endif .endif
add sp, sp, #PT_REGS_SIZE - S_SP add sp, sp, #PT_REGS_SIZE - S_SP
movs pc, lr @ return & move spsr_svc into cpsr movs pc, lr @ return & move spsr_svc into cpsr
1: bug "Returning to usermode but unexpected PSR bits set?", \@
#endif /* !CONFIG_THUMB2_KERNEL */ #endif /* !CONFIG_THUMB2_KERNEL */
.endm .endm
......
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