This patch cleans up and fixes bugs in resume_execution on x86-64. Kprobes for x86-64 may cause a kernel crash if it inserted on "iret" instruction. "call absolute" is invalid on x86-64, so we don't need treat it.
- Change the processing order as same as x86-32. - Add "iret"(0xcf) case. - Remove next_rip local variable. Signed-off-by: Masami Hiramatsu <[EMAIL PROTECTED]> --- arch/x86/kernel/kprobes_64.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) Index: 2.6.24-rc4-mm1/arch/x86/kernel/kprobes_64.c =================================================================== --- 2.6.24-rc4-mm1.orig/arch/x86/kernel/kprobes_64.c +++ 2.6.24-rc4-mm1/arch/x86/kernel/kprobes_64.c @@ -498,7 +498,6 @@ static void __kprobes resume_execution(s struct pt_regs *regs, struct kprobe_ctlblk *kcb) { unsigned long *tos = (unsigned long *)regs->sp; - unsigned long next_rip = 0; unsigned long copy_rip = (unsigned long)p->ainsn.insn; unsigned long orig_rip = (unsigned long)p->addr; kprobe_opcode_t *insn = p->ainsn.insn; @@ -507,48 +506,44 @@ static void __kprobes resume_execution(s if (*insn >= 0x40 && *insn <= 0x4f) insn++; + regs->flags &= ~TF_MASK; switch (*insn) { - case 0x9c: /* pushfl */ + case 0x9c: /* pushfl */ *tos &= ~(TF_MASK | IF_MASK); *tos |= kcb->kprobe_old_rflags; break; - case 0xc3: /* ret/lret */ - case 0xcb: - case 0xc2: + case 0xc2: /* iret/ret/lret */ + case 0xc3: case 0xca: - regs->flags &= ~TF_MASK; - /* ip is already adjusted, no more changes required*/ - return; - case 0xe8: /* call relative - Fix return addr */ + case 0xcb: + case 0xcf: + case 0xea: /* jmp absolute -- ip is correct */ + /* ip is already adjusted, no more changes required */ + goto no_change; + case 0xe8: /* call relative - Fix return addr */ *tos = orig_rip + (*tos - copy_rip); break; case 0xff: if ((insn[1] & 0x30) == 0x10) { /* call absolute, indirect */ /* Fix return addr; ip is correct. */ - next_rip = regs->ip; *tos = orig_rip + (*tos - copy_rip); + goto no_change; } else if (((insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ ((insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ /* ip is correct. */ - next_rip = regs->ip; + goto no_change; } - break; - case 0xea: /* jmp absolute -- ip is correct */ - next_rip = regs->ip; - break; default: break; } - regs->flags &= ~TF_MASK; - if (next_rip) { - regs->ip = next_rip; - } else { - regs->ip = orig_rip + (regs->ip - copy_rip); - } + regs->ip = orig_rip + (regs->ip - copy_rip); +no_change: restore_btf(); + + return; } int __kprobes post_kprobe_handler(struct pt_regs *regs) -- Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [EMAIL PROTECTED], [EMAIL PROTECTED] -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/