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

Nicolas Pitre nico at fluxnic.net
Fri Mar 26 08:32:51 EDT 2010


On Fri, 26 Mar 2010, Mika Westerberg wrote:

> 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>

Acked-by: Nicolas Pitre <nico at marvell.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
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 



More information about the linux-arm-kernel mailing list