Commit 29b6cd79 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Ingo Molnar

x86: jprobe bugfix

jprobe for x86-64 may cause kernel page fault when the jprobe_return()
is called from incorrect function.

- Use jprobe_saved_regs instead getting it from stack.
  (Especially on x86-64, it may get incorrect data, because
   pt_regs can not be get by using container_of(rsp))
- Change the type of stack pointer to unsigned long *.
Signed-off-by: default avatarMasami Hiramatsu <mhiramat@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent b4be6258
...@@ -727,9 +727,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) ...@@ -727,9 +727,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
if (&regs->esp != kcb->jprobe_saved_esp) { if (&regs->esp != kcb->jprobe_saved_esp) {
struct pt_regs *saved_regs = struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
container_of(kcb->jprobe_saved_esp,
struct pt_regs, esp);
printk("current esp %p does not match saved esp %p\n", printk("current esp %p does not match saved esp %p\n",
&regs->esp, kcb->jprobe_saved_esp); &regs->esp, kcb->jprobe_saved_esp);
printk("Saved registers for jprobe %p\n", jp); printk("Saved registers for jprobe %p\n", jp);
......
...@@ -716,10 +716,8 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) ...@@ -716,10 +716,8 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
struct jprobe *jp = container_of(p, struct jprobe, kp); struct jprobe *jp = container_of(p, struct jprobe, kp);
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) { if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
if ((long *)regs->rsp != kcb->jprobe_saved_rsp) { if ((unsigned long *)regs->rsp != kcb->jprobe_saved_rsp) {
struct pt_regs *saved_regs = struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
container_of(kcb->jprobe_saved_rsp,
struct pt_regs, rsp);
printk("current rsp %p does not match saved rsp %p\n", printk("current rsp %p does not match saved rsp %p\n",
(long *)regs->rsp, kcb->jprobe_saved_rsp); (long *)regs->rsp, kcb->jprobe_saved_rsp);
printk("Saved registers for jprobe %p\n", jp); printk("Saved registers for jprobe %p\n", jp);
......
...@@ -73,7 +73,7 @@ struct kprobe_ctlblk { ...@@ -73,7 +73,7 @@ struct kprobe_ctlblk {
unsigned long kprobe_status; unsigned long kprobe_status;
unsigned long kprobe_old_eflags; unsigned long kprobe_old_eflags;
unsigned long kprobe_saved_eflags; unsigned long kprobe_saved_eflags;
long *jprobe_saved_esp; unsigned long *jprobe_saved_esp;
struct pt_regs jprobe_saved_regs; struct pt_regs jprobe_saved_regs;
kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
struct prev_kprobe prev_kprobe; struct prev_kprobe prev_kprobe;
......
...@@ -66,7 +66,7 @@ struct kprobe_ctlblk { ...@@ -66,7 +66,7 @@ struct kprobe_ctlblk {
unsigned long kprobe_status; unsigned long kprobe_status;
unsigned long kprobe_old_rflags; unsigned long kprobe_old_rflags;
unsigned long kprobe_saved_rflags; unsigned long kprobe_saved_rflags;
long *jprobe_saved_rsp; unsigned long *jprobe_saved_rsp;
struct pt_regs jprobe_saved_regs; struct pt_regs jprobe_saved_regs;
kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
struct prev_kprobe prev_kprobe; struct prev_kprobe prev_kprobe;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment