diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-10-17 12:59:20 +0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-10-17 12:59:20 +0400 |
commit | 0b4f5b1d6385826093dc3cd9035b186f0d77a5dc (patch) | |
tree | e7602057216d3de837995b267a281ae09d899a26 /arch/powerpc/lib/sstep.c | |
parent | 939ccba437da1726a5c8a5b702a47d473da927ae (diff) | |
parent | 9f0d3c2781baa1102108e16efbe640dd74564a7c (diff) | |
download | linux-0b4f5b1d6385826093dc3cd9035b186f0d77a5dc.tar.xz |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
To obtain new flag FLOWI_FLAG_KNOWN_NH to fix netfilter's xt_TEE target.
Diffstat (limited to 'arch/powerpc/lib/sstep.c')
-rw-r--r-- | arch/powerpc/lib/sstep.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 9a52349874ee..e15c521846ca 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -566,7 +566,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) unsigned long int ea; unsigned int cr, mb, me, sh; int err; - unsigned long old_ra; + unsigned long old_ra, val3; long ival; opcode = instr >> 26; @@ -1486,11 +1486,43 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) goto ldst_done; case 36: /* stw */ - case 37: /* stwu */ val = regs->gpr[rd]; err = write_mem(val, dform_ea(instr, regs), 4, regs); goto ldst_done; + case 37: /* stwu */ + val = regs->gpr[rd]; + val3 = dform_ea(instr, regs); + /* + * For PPC32 we always use stwu to change stack point with r1. So + * this emulated store may corrupt the exception frame, now we + * have to provide the exception frame trampoline, which is pushed + * below the kprobed function stack. So we only update gpr[1] but + * don't emulate the real store operation. We will do real store + * operation safely in exception return code by checking this flag. + */ + if ((ra == 1) && !(regs->msr & MSR_PR) \ + && (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) { + /* + * Check if we will touch kernel sack overflow + */ + if (val3 - STACK_INT_FRAME_SIZE <= current->thread.ksp_limit) { + printk(KERN_CRIT "Can't kprobe this since Kernel stack overflow.\n"); + err = -EINVAL; + break; + } + + /* + * Check if we already set since that means we'll + * lose the previous value. + */ + WARN_ON(test_thread_flag(TIF_EMULATE_STACK_STORE)); + set_thread_flag(TIF_EMULATE_STACK_STORE); + err = 0; + } else + err = write_mem(val, val3, 4, regs); + goto ldst_done; + case 38: /* stb */ case 39: /* stbu */ val = regs->gpr[rd]; |