[PATCH] arm: kprobes: fix register corruption with jprobes

Mika Westerberg ext-mika.1.westerberg at nokia.com
Fri Mar 26 02:59:00 EDT 2010


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)
    bd60: c050b3e8 ce94bd60 00000025 c050b424 ce9a1822 00000025 00000025 ce94be58
    bd80: 0000004a c050ca1c ce9a1822 c002c070 ffffffff fa200000 0000004a c02991e0
    bda0: ce9a1822 e92d41f0 00000000 c039a890 c050c9e0 cfc72e00 0000004a c050ca1c
    bdc0: ce9a1822 cf5d4000 c0aa453c a0000013 00000000 ce94bde8 00000006 c02997c8
    bde0: c80a0013 ffffffff 0000004a cfc72e00 cf4d0440 00000001 c050c9e0 cfc72e00
    be00: 0000004a c050ca1c ce9a1822 cf5d4000 c0aa453c a0000013 c050c9e0 ce94be18
    be20: 0000004a c050ca1c ce9a1822 0000004a 0000004a 00000000 00000022 00000000
    be40: ce9a1822 c002c070 ffffffff fa200000 00000022 c02991e0 00000001 cf4d0810
    be60: 00000002 00004f48 c0aa453c 20000013 00000022 00000000 ce9a1822 cf5d4000
    be80: c0aa453c a0000013 000000d4 ce94bea0 c0074d40 c0299078 20000013 ffffffff
    bea0: 00000000 cfd33338 00000022 c018d8d4 c02b56fc cf4d0440 cf5d4000 ce9a1800
    bec0: 00000022 cf5d4574 cf420680 ce94a000 ce9a1800 c017b2c4 cf5d41f0 cf5d4130
    bee0: 60000013 00000000 cf4d0440 c004e6b8 cf5d4214 cf5d4214 c03a5870 00000022
    bf00: 00000022 00000000 cf5d4000 ce94a000 00000022 00000000 cf420680 c0178b3c
    bf20: cf4d0440 4001e000 c017b070 cf5fd440 00000000 c00aeb5c 00000001 cf420680
    bf40: 4001e000 ce94bf80 00000022 00000022 ce94a000 00000001 bef8a89c c00af3dc
    bf60: cf420680 4001e000 00000000 00000000 cf420680 00000022 4001e000 c00af530
    bf80: 00000000 00000000 00000022 00000000 00000022 4001e000 40185608 00000004
    bfa0: c002caa4 c002c900 00000022 4001e000 00000001 4001e000 00000022 00000000
    bfc0: 00000022 4001e000 40185608 00000004 00000022 00000014 00000001 bef8a89c
    bfe0: 00000000 bef8a880 400c7b88 401176bc 60000010 00000001 80cb0021 80cb0421
    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: Mika Westerberg <ext-mika.1.westerberg at nokia.com>
---
 arch/arm/kernel/kprobes.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 60c62c3..610e0f5 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -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))
-- 
1.5.6.5




More information about the linux-arm-kernel mailing list