]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
[PATCH] kprobes: bad manipulation of 2 byte opcode on x86_64
authorSatoshi Oshima <soshima@redhat.com>
Sat, 20 May 2006 22:00:21 +0000 (15:00 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 21 May 2006 19:59:21 +0000 (12:59 -0700)
Problem:

If we put a probe onto a callq instruction and the probe is executed,
kernel panic of Bad RIP value occurs.

Root cause:

If resume_execution() found 0xff at first byte of p->ainsn.insn, it must
check the _second_ byte.  But current resume_execution check _first_ byte
again.

I changed it checks second byte of p->ainsn.insn.

Kprobes on i386 don't have this problem, because the implementation is a
little bit different from x86_64.

Cc: Andi Kleen <ak@muc.de>
Signed-off-by: Satoshi Oshima <soshima@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/x86_64/kernel/kprobes.c

index 1eaa5dae6174ff57b514a56828f07e6f8ed0a149..fa1d19ca700ae82a23df77f068bee660e47f80f2 100644 (file)
@@ -514,13 +514,13 @@ static void __kprobes resume_execution(struct kprobe *p,
                *tos = orig_rip + (*tos - copy_rip);
                break;
        case 0xff:
-               if ((*insn & 0x30) == 0x10) {
+               if ((insn[1] & 0x30) == 0x10) {
                        /* call absolute, indirect */
                        /* Fix return addr; rip is correct. */
                        next_rip = regs->rip;
                        *tos = orig_rip + (*tos - copy_rip);
-               } else if (((*insn & 0x31) == 0x20) ||  /* jmp near, absolute indirect */
-                          ((*insn & 0x31) == 0x21)) {  /* jmp far, absolute indirect */
+               } else if (((insn[1] & 0x31) == 0x20) ||        /* jmp near, absolute indirect */
+                          ((insn[1] & 0x31) == 0x21)) {        /* jmp far, absolute indirect */
                        /* rip is correct. */
                        next_rip = regs->rip;
                }