summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSatoshi Oshima <soshima@redhat.com>2006-05-20 15:00:21 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-05-21 12:59:21 -0700
commitdc49e3445aa703eb7fd33c7ddb7e4a7bbcf06d30 (patch)
treeeb164ad61b92f2df2ffab9628adffe06e635c8e2
parentbe0d03f1c3d3612fe2b6aa451ae87a89382c9231 (diff)
downloadlinux-dc49e3445aa703eb7fd33c7ddb7e4a7bbcf06d30.tar.gz
linux-dc49e3445aa703eb7fd33c7ddb7e4a7bbcf06d30.tar.bz2
linux-dc49e3445aa703eb7fd33c7ddb7e4a7bbcf06d30.zip
[PATCH] kprobes: bad manipulation of 2 byte opcode on x86_64
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>
-rw-r--r--arch/x86_64/kernel/kprobes.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 1eaa5dae6174..fa1d19ca700a 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -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;
}