aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/kprobes/ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/kprobes/ftrace.c')
-rw-r--r--arch/x86/kernel/kprobes/ftrace.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
index 717b02a22e67..5f8f0b3cc674 100644
--- a/arch/x86/kernel/kprobes/ftrace.c
+++ b/arch/x86/kernel/kprobes/ftrace.c
@@ -27,7 +27,7 @@
27 27
28static nokprobe_inline 28static nokprobe_inline
29int __skip_singlestep(struct kprobe *p, struct pt_regs *regs, 29int __skip_singlestep(struct kprobe *p, struct pt_regs *regs,
30 struct kprobe_ctlblk *kcb) 30 struct kprobe_ctlblk *kcb, unsigned long orig_ip)
31{ 31{
32 /* 32 /*
33 * Emulate singlestep (and also recover regs->ip) 33 * Emulate singlestep (and also recover regs->ip)
@@ -39,6 +39,8 @@ int __skip_singlestep(struct kprobe *p, struct pt_regs *regs,
39 p->post_handler(p, regs, 0); 39 p->post_handler(p, regs, 0);
40 } 40 }
41 __this_cpu_write(current_kprobe, NULL); 41 __this_cpu_write(current_kprobe, NULL);
42 if (orig_ip)
43 regs->ip = orig_ip;
42 return 1; 44 return 1;
43} 45}
44 46
@@ -46,7 +48,7 @@ int skip_singlestep(struct kprobe *p, struct pt_regs *regs,
46 struct kprobe_ctlblk *kcb) 48 struct kprobe_ctlblk *kcb)
47{ 49{
48 if (kprobe_ftrace(p)) 50 if (kprobe_ftrace(p))
49 return __skip_singlestep(p, regs, kcb); 51 return __skip_singlestep(p, regs, kcb, 0);
50 else 52 else
51 return 0; 53 return 0;
52} 54}
@@ -71,13 +73,14 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
71 if (kprobe_running()) { 73 if (kprobe_running()) {
72 kprobes_inc_nmissed_count(p); 74 kprobes_inc_nmissed_count(p);
73 } else { 75 } else {
76 unsigned long orig_ip = regs->ip;
74 /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */ 77 /* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
75 regs->ip = ip + sizeof(kprobe_opcode_t); 78 regs->ip = ip + sizeof(kprobe_opcode_t);
76 79
77 __this_cpu_write(current_kprobe, p); 80 __this_cpu_write(current_kprobe, p);
78 kcb->kprobe_status = KPROBE_HIT_ACTIVE; 81 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
79 if (!p->pre_handler || !p->pre_handler(p, regs)) 82 if (!p->pre_handler || !p->pre_handler(p, regs))
80 __skip_singlestep(p, regs, kcb); 83 __skip_singlestep(p, regs, kcb, orig_ip);
81 /* 84 /*
82 * If pre_handler returns !0, it sets regs->ip and 85 * If pre_handler returns !0, it sets regs->ip and
83 * resets current kprobe. 86 * resets current kprobe.