Skip to content

Commit

Permalink
ARCv2: STAR 9000808988: signals involving Delay Slot
Browse files Browse the repository at this point in the history
[ Upstream commit 0d7b885 ]

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 <[email protected]>
Signed-off-by: Vineet Gupta <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
vineetgarc authored and Sasha Levin committed Sep 1, 2016
1 parent 61f53d4 commit 6c262bd
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 7 deletions.
17 changes: 10 additions & 7 deletions arch/arc/include/asm/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@
POP r13
.endm

#define OFF_USER_R25_FROM_R24 (SZ_CALLEE_REGS + SZ_PT_REGS - 8)/4

/*--------------------------------------------------------------
* Collect User Mode callee regs as struct callee_regs - needed by
* fork/do_signal/unaligned-access-emulation.
Expand All @@ -157,12 +155,13 @@
*-------------------------------------------------------------*/
.macro SAVE_CALLEE_SAVED_USER

mov r12, sp ; save SP as ref to pt_regs
SAVE_R13_TO_R24

#ifdef CONFIG_ARC_CURR_IN_REG
; Retrieve orig r25 and save it on stack
ld.as r12, [sp, OFF_USER_R25_FROM_R24]
st.a r12, [sp, -4]
; Retrieve orig r25 and save it with rest of callee_regs
ld.as r12, [r12, PT_user_r25]
PUSH r12
#else
PUSH r25
#endif
Expand Down Expand Up @@ -209,12 +208,16 @@
.macro RESTORE_CALLEE_SAVED_USER

#ifdef CONFIG_ARC_CURR_IN_REG
ld.ab r12, [sp, 4]
st.as r12, [sp, OFF_USER_R25_FROM_R24]
POP r12
#else
POP r25
#endif
RESTORE_R24_TO_R13

; SP is back to start of pt_regs
#ifdef CONFIG_ARC_CURR_IN_REG
st.as r12, [sp, PT_user_r25]
#endif
.endm

/*--------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions arch/arc/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,7 @@ int main(void)

DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs));
DEFINE(SZ_PT_REGS, sizeof(struct pt_regs));
DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25));

return 0;
}

0 comments on commit 6c262bd

Please sign in to comment.