diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2014-10-07 04:42:13 -0400 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2015-06-22 04:36:55 -0400 |
commit | 0d7b8855a05c099a5c65a8d49a1e604198021f56 (patch) | |
tree | ca804ebd88dfcf49965c23251577e505aa440a2e | |
parent | 4255b07f2c9c43540149ed823faf5ac8476cccee (diff) |
ARCv2: STAR 9000808988: signals involving Delay Slot
Reported by Anton as LTP:munmap01 failing with Illegal Instruction
Exception.
--------------------->8--------------------------------------
mmap2(NULL, 24576, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 0x200d2000
munmap(0x200d2000, 24576) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x200d2000}
---
potentially unexpected fatal signal 4.
Path: /munmap01
CPU: 0 PID: 61 Comm: munmap01 Not tainted 3.13.0-g5d5c46d9a556 #8
task: 9f1a8000 ti: 9f154000 task.ti: 9f154000
[ECR ]: 0x00020100 => Illegal Insn
[EFA ]: 0x0001354c
[BLINK ]: 0x200515d4
[ERET ]: 0x1354c
@off 0x1354c in [/munmap01]
VMA: 0x00010000 to 0x00018000
[STAT32]: 0x800802c0
...
--------------------->8--------------------------------------
The issue was
1. munmap01 accessed unmapped memory (on purpose) with signal handler
installed for SIGSEGV
2. The faulting instruction happened to be in Delay Slot
00011864 <main>:
11908: bl.d 13284 <tst_resm>
1190c: stb r16,[r2]
3. kernel sets up the reg file for signal handler and correctly clears
the DE bit in pt_regs->status32 placeholder
4. However RESTORE_CALLEE_SAVED_USER macro is not adjusted for ARCv2,
and it over-writes the above with orig/stale value of status32
5. After RTIE, userspace signal handler executes a non branch
instruction with DE bit set, triggering Illegal Instruction Exception.
Reported-by: Anton Kolesov <akolesov@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
-rw-r--r-- | arch/arc/include/asm/entry.h | 17 | ||||
-rw-r--r-- | arch/arc/kernel/asm-offsets.c | 2 |
2 files changed, 12 insertions, 7 deletions
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index 29d0ab6e10f5..ad7860c5ce15 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h | |||
@@ -125,8 +125,6 @@ | |||
125 | POP r13 | 125 | POP r13 |
126 | .endm | 126 | .endm |
127 | 127 | ||
128 | #define OFF_USER_R25_FROM_R24 (SZ_CALLEE_REGS + SZ_PT_REGS - 8)/4 | ||
129 | |||
130 | /*-------------------------------------------------------------- | 128 | /*-------------------------------------------------------------- |
131 | * Collect User Mode callee regs as struct callee_regs - needed by | 129 | * Collect User Mode callee regs as struct callee_regs - needed by |
132 | * fork/do_signal/unaligned-access-emulation. | 130 | * fork/do_signal/unaligned-access-emulation. |
@@ -139,12 +137,13 @@ | |||
139 | *-------------------------------------------------------------*/ | 137 | *-------------------------------------------------------------*/ |
140 | .macro SAVE_CALLEE_SAVED_USER | 138 | .macro SAVE_CALLEE_SAVED_USER |
141 | 139 | ||
140 | mov r12, sp ; save SP as ref to pt_regs | ||
142 | SAVE_R13_TO_R24 | 141 | SAVE_R13_TO_R24 |
143 | 142 | ||
144 | #ifdef CONFIG_ARC_CURR_IN_REG | 143 | #ifdef CONFIG_ARC_CURR_IN_REG |
145 | ; Retrieve orig r25 and save it on stack | 144 | ; Retrieve orig r25 and save it with rest of callee_regs |
146 | ld.as r12, [sp, OFF_USER_R25_FROM_R24] | 145 | ld.as r12, [r12, PT_user_r25] |
147 | st.a r12, [sp, -4] | 146 | PUSH r12 |
148 | #else | 147 | #else |
149 | PUSH r25 | 148 | PUSH r25 |
150 | #endif | 149 | #endif |
@@ -191,12 +190,16 @@ | |||
191 | .macro RESTORE_CALLEE_SAVED_USER | 190 | .macro RESTORE_CALLEE_SAVED_USER |
192 | 191 | ||
193 | #ifdef CONFIG_ARC_CURR_IN_REG | 192 | #ifdef CONFIG_ARC_CURR_IN_REG |
194 | ld.ab r12, [sp, 4] | 193 | POP r12 |
195 | st.as r12, [sp, OFF_USER_R25_FROM_R24] | ||
196 | #else | 194 | #else |
197 | POP r25 | 195 | POP r25 |
198 | #endif | 196 | #endif |
199 | RESTORE_R24_TO_R13 | 197 | RESTORE_R24_TO_R13 |
198 | |||
199 | ; SP is back to start of pt_regs | ||
200 | #ifdef CONFIG_ARC_CURR_IN_REG | ||
201 | st.as r12, [sp, PT_user_r25] | ||
202 | #endif | ||
200 | .endm | 203 | .endm |
201 | 204 | ||
202 | /*-------------------------------------------------------------- | 205 | /*-------------------------------------------------------------- |
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index b9cf23313273..605281f5b301 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c | |||
@@ -60,5 +60,7 @@ int main(void) | |||
60 | 60 | ||
61 | DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); | 61 | DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); |
62 | DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); | 62 | DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); |
63 | DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25)); | ||
64 | |||
63 | return 0; | 65 | return 0; |
64 | } | 66 | } |