aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/kprobes.c')
-rw-r--r--arch/i386/kernel/kprobes.c176
1 files changed, 160 insertions, 16 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 59ff9b455069..3762f6b35ab2 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -23,6 +23,9 @@
23 * Rusty Russell). 23 * Rusty Russell).
24 * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes 24 * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
25 * interface to access function arguments. 25 * interface to access function arguments.
26 * 2005-May Hien Nguyen <hien@us.ibm.com>, Jim Keniston
27 * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
28 * <prasanna@in.ibm.com> added function-return probes.
26 */ 29 */
27 30
28#include <linux/config.h> 31#include <linux/config.h>
@@ -30,15 +33,14 @@
30#include <linux/ptrace.h> 33#include <linux/ptrace.h>
31#include <linux/spinlock.h> 34#include <linux/spinlock.h>
32#include <linux/preempt.h> 35#include <linux/preempt.h>
36#include <asm/cacheflush.h>
33#include <asm/kdebug.h> 37#include <asm/kdebug.h>
34#include <asm/desc.h> 38#include <asm/desc.h>
35 39
36/* kprobe_status settings */
37#define KPROBE_HIT_ACTIVE 0x00000001
38#define KPROBE_HIT_SS 0x00000002
39
40static struct kprobe *current_kprobe; 40static struct kprobe *current_kprobe;
41static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags; 41static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags;
42static struct kprobe *kprobe_prev;
43static unsigned long kprobe_status_prev, kprobe_old_eflags_prev, kprobe_saved_eflags_prev;
42static struct pt_regs jprobe_saved_regs; 44static struct pt_regs jprobe_saved_regs;
43static long *jprobe_saved_esp; 45static long *jprobe_saved_esp;
44/* copy of the kernel stack at the probe fire time */ 46/* copy of the kernel stack at the probe fire time */
@@ -68,16 +70,50 @@ int arch_prepare_kprobe(struct kprobe *p)
68void arch_copy_kprobe(struct kprobe *p) 70void arch_copy_kprobe(struct kprobe *p)
69{ 71{
70 memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); 72 memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
73 p->opcode = *p->addr;
71} 74}
72 75
73void arch_remove_kprobe(struct kprobe *p) 76void arch_arm_kprobe(struct kprobe *p)
74{ 77{
78 *p->addr = BREAKPOINT_INSTRUCTION;
79 flush_icache_range((unsigned long) p->addr,
80 (unsigned long) p->addr + sizeof(kprobe_opcode_t));
75} 81}
76 82
77static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs) 83void arch_disarm_kprobe(struct kprobe *p)
78{ 84{
79 *p->addr = p->opcode; 85 *p->addr = p->opcode;
80 regs->eip = (unsigned long)p->addr; 86 flush_icache_range((unsigned long) p->addr,
87 (unsigned long) p->addr + sizeof(kprobe_opcode_t));
88}
89
90void arch_remove_kprobe(struct kprobe *p)
91{
92}
93
94static inline void save_previous_kprobe(void)
95{
96 kprobe_prev = current_kprobe;
97 kprobe_status_prev = kprobe_status;
98 kprobe_old_eflags_prev = kprobe_old_eflags;
99 kprobe_saved_eflags_prev = kprobe_saved_eflags;
100}
101
102static inline void restore_previous_kprobe(void)
103{
104 current_kprobe = kprobe_prev;
105 kprobe_status = kprobe_status_prev;
106 kprobe_old_eflags = kprobe_old_eflags_prev;
107 kprobe_saved_eflags = kprobe_saved_eflags_prev;
108}
109
110static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
111{
112 current_kprobe = p;
113 kprobe_saved_eflags = kprobe_old_eflags
114 = (regs->eflags & (TF_MASK | IF_MASK));
115 if (is_IF_modifier(p->opcode))
116 kprobe_saved_eflags &= ~IF_MASK;
81} 117}
82 118
83static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) 119static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -91,6 +127,50 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
91 regs->eip = (unsigned long)&p->ainsn.insn; 127 regs->eip = (unsigned long)&p->ainsn.insn;
92} 128}
93 129
130struct task_struct *arch_get_kprobe_task(void *ptr)
131{
132 return ((struct thread_info *) (((unsigned long) ptr) &
133 (~(THREAD_SIZE -1))))->task;
134}
135
136void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
137{
138 unsigned long *sara = (unsigned long *)&regs->esp;
139 struct kretprobe_instance *ri;
140 static void *orig_ret_addr;
141
142 /*
143 * Save the return address when the return probe hits
144 * the first time, and use it to populate the (krprobe
145 * instance)->ret_addr for subsequent return probes at
146 * the same addrress since stack address would have
147 * the kretprobe_trampoline by then.
148 */
149 if (((void*) *sara) != kretprobe_trampoline)
150 orig_ret_addr = (void*) *sara;
151
152 if ((ri = get_free_rp_inst(rp)) != NULL) {
153 ri->rp = rp;
154 ri->stack_addr = sara;
155 ri->ret_addr = orig_ret_addr;
156 add_rp_inst(ri);
157 /* Replace the return addr with trampoline addr */
158 *sara = (unsigned long) &kretprobe_trampoline;
159 } else {
160 rp->nmissed++;
161 }
162}
163
164void arch_kprobe_flush_task(struct task_struct *tk)
165{
166 struct kretprobe_instance *ri;
167 while ((ri = get_rp_inst_tsk(tk)) != NULL) {
168 *((unsigned long *)(ri->stack_addr)) =
169 (unsigned long) ri->ret_addr;
170 recycle_rp_inst(ri);
171 }
172}
173
94/* 174/*
95 * Interrupts are disabled on entry as trap3 is an interrupt gate and they 175 * Interrupts are disabled on entry as trap3 is an interrupt gate and they
96 * remain disabled thorough out this function. 176 * remain disabled thorough out this function.
@@ -127,8 +207,18 @@ static int kprobe_handler(struct pt_regs *regs)
127 unlock_kprobes(); 207 unlock_kprobes();
128 goto no_kprobe; 208 goto no_kprobe;
129 } 209 }
130 disarm_kprobe(p, regs); 210 /* We have reentered the kprobe_handler(), since
131 ret = 1; 211 * another probe was hit while within the handler.
212 * We here save the original kprobes variables and
213 * just single step on the instruction of the new probe
214 * without calling any user handlers.
215 */
216 save_previous_kprobe();
217 set_current_kprobe(p, regs);
218 p->nmissed++;
219 prepare_singlestep(p, regs);
220 kprobe_status = KPROBE_REENTER;
221 return 1;
132 } else { 222 } else {
133 p = current_kprobe; 223 p = current_kprobe;
134 if (p->break_handler && p->break_handler(p, regs)) { 224 if (p->break_handler && p->break_handler(p, regs)) {
@@ -163,11 +253,7 @@ static int kprobe_handler(struct pt_regs *regs)
163 } 253 }
164 254
165 kprobe_status = KPROBE_HIT_ACTIVE; 255 kprobe_status = KPROBE_HIT_ACTIVE;
166 current_kprobe = p; 256 set_current_kprobe(p, regs);
167 kprobe_saved_eflags = kprobe_old_eflags
168 = (regs->eflags & (TF_MASK | IF_MASK));
169 if (is_IF_modifier(p->opcode))
170 kprobe_saved_eflags &= ~IF_MASK;
171 257
172 if (p->pre_handler && p->pre_handler(p, regs)) 258 if (p->pre_handler && p->pre_handler(p, regs))
173 /* handler has already set things up, so skip ss setup */ 259 /* handler has already set things up, so skip ss setup */
@@ -184,6 +270,55 @@ no_kprobe:
184} 270}
185 271
186/* 272/*
273 * For function-return probes, init_kprobes() establishes a probepoint
274 * here. When a retprobed function returns, this probe is hit and
275 * trampoline_probe_handler() runs, calling the kretprobe's handler.
276 */
277 void kretprobe_trampoline_holder(void)
278 {
279 asm volatile ( ".global kretprobe_trampoline\n"
280 "kretprobe_trampoline: \n"
281 "nop\n");
282 }
283
284/*
285 * Called when we hit the probe point at kretprobe_trampoline
286 */
287int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
288{
289 struct task_struct *tsk;
290 struct kretprobe_instance *ri;
291 struct hlist_head *head;
292 struct hlist_node *node;
293 unsigned long *sara = ((unsigned long *) &regs->esp) - 1;
294
295 tsk = arch_get_kprobe_task(sara);
296 head = kretprobe_inst_table_head(tsk);
297
298 hlist_for_each_entry(ri, node, head, hlist) {
299 if (ri->stack_addr == sara && ri->rp) {
300 if (ri->rp->handler)
301 ri->rp->handler(ri, regs);
302 }
303 }
304 return 0;
305}
306
307void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
308 unsigned long flags)
309{
310 struct kretprobe_instance *ri;
311 /* RA already popped */
312 unsigned long *sara = ((unsigned long *)&regs->esp) - 1;
313
314 while ((ri = get_rp_inst(sara))) {
315 regs->eip = (unsigned long)ri->ret_addr;
316 recycle_rp_inst(ri);
317 }
318 regs->eflags &= ~TF_MASK;
319}
320
321/*
187 * Called after single-stepping. p->addr is the address of the 322 * Called after single-stepping. p->addr is the address of the
188 * instruction whose first byte has been replaced by the "int 3" 323 * instruction whose first byte has been replaced by the "int 3"
189 * instruction. To avoid the SMP problems that can occur when we 324 * instruction. To avoid the SMP problems that can occur when we
@@ -263,13 +398,22 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
263 if (!kprobe_running()) 398 if (!kprobe_running())
264 return 0; 399 return 0;
265 400
266 if (current_kprobe->post_handler) 401 if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
402 kprobe_status = KPROBE_HIT_SSDONE;
267 current_kprobe->post_handler(current_kprobe, regs, 0); 403 current_kprobe->post_handler(current_kprobe, regs, 0);
404 }
268 405
269 resume_execution(current_kprobe, regs); 406 if (current_kprobe->post_handler != trampoline_post_handler)
407 resume_execution(current_kprobe, regs);
270 regs->eflags |= kprobe_saved_eflags; 408 regs->eflags |= kprobe_saved_eflags;
271 409
410 /*Restore back the original saved kprobes variables and continue. */
411 if (kprobe_status == KPROBE_REENTER) {
412 restore_previous_kprobe();
413 goto out;
414 }
272 unlock_kprobes(); 415 unlock_kprobes();
416out:
273 preempt_enable_no_resched(); 417 preempt_enable_no_resched();
274 418
275 /* 419 /*