Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 782a0fd1 authored by Mika Westerberg's avatar Mika Westerberg Committed by Russell King
Browse files

ARM: 6005/1: arm: kprobes: fix register corruption with jprobes



Current implementation of jprobes allocates empty pt_regs from the
stack which is then passed to kprobe_handler() and eventually to
singlestep().  Now when instruction being simulated is STMFD (like
in normal function prologues without CONFIG_FRAME_POINTER), stores
using SP actually write over top of the fabricated pt_regs
structure.

This can be reproduced for example by using LKDTM module:
    # modprobe lkdtm
    # mount -t debugfs none /sys/kernel/debug
    # echo PANIC > /sys/kernel/debug/provoke-crash/INT_HW_IRQ_EN

after this, it fails with corrupted registers (before the requested crash would occur):

lkdtm: Crash point INT_HW_IRQ_EN of type PANIC hit, trigger in 9 rounds
lkdtm: Crash point INT_HW_IRQ_EN of type PANIC hit, trigger in 8 rounds
Internal error: Oops - undefined instruction: 0 [#1]
last sysfs file: /sys/devices/platform/serial8250.0/sleep_timeout
Modules linked in: lkdtm
CPU: 0    Not tainted  (2.6.34-rc2 #69)
PC is at irq_desc+0x1638/0xeeb0
LR is at 0x25
pc : [<c050b428>]    lr : [<00000025>]    psr: c80a0013
sp : ce94bd60  ip : c050b3e8  fp : a0000013
r10: c0aa453c  r9 : cf5d4000  r8 : ce9a1822
r7 : c050b424  r6 : 00000025  r5 : c039d8f8  r4 : c050b3e8
r3 : 00000001  r2 : cf4d0440  r1 : c039d8f8  r0 : 00000020
Flags: NZcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 10c5387d  Table: 8e804019  DAC: 00000015
Process sh (pid: 496, stack limit = 0xce94a2e8)
Stack: (0xce94bd60 to 0xce94c000)
[...]
Code: 000002cd 00000000 00000000 00000001 (dead4ead)
---[ end trace 2b46d5f2b682f370 ]---
Kernel panic - not syncing: Fatal exception in interrupt

This patch allocates enough space (2 * sizeof(struct pt_regs)) from
the stack to prevent such corruption.

Signed-off-by: default avatarMika Westerberg <ext-mika.1.westerberg@nokia.com>
Acked-by: default avatarNicolas Pitre <nico@marvell.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 367d6acc
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -393,6 +393,14 @@ void __kprobes jprobe_return(void)
		/*
		 * Setup an empty pt_regs. Fill SP and PC fields as
		 * they're needed by longjmp_break_handler.
		 *
		 * We allocate some slack between the original SP and start of
		 * our fabricated regs. To be precise we want to have worst case
		 * covered which is STMFD with all 16 regs so we allocate 2 *
		 * sizeof(struct_pt_regs)).
		 *
		 * This is to prevent any simulated instruction from writing
		 * over the regs when they are accessing the stack.
		 */
		"sub    sp, %0, %1		\n\t"
		"ldr    r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t"
@@ -410,7 +418,7 @@ void __kprobes jprobe_return(void)
		"ldmia	sp, {r0 - pc}		\n\t"
		:
		: "r" (kcb->jprobe_saved_regs.ARM_sp),
		  "I" (sizeof(struct pt_regs)),
		  "I" (sizeof(struct pt_regs) * 2),
		  "J" (offsetof(struct pt_regs, ARM_sp)),
		  "J" (offsetof(struct pt_regs, ARM_pc)),
		  "J" (offsetof(struct pt_regs, ARM_cpsr))