aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/kprobes.h28
-rw-r--r--kernel/kprobes.c69
2 files changed, 22 insertions, 75 deletions
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index d304d4579856..b7a194c4362a 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -104,33 +104,12 @@ struct jprobe {
104}; 104};
105 105
106#ifdef ARCH_SUPPORTS_KRETPROBES 106#ifdef ARCH_SUPPORTS_KRETPROBES
107extern int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs);
108extern void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
109 unsigned long flags);
110extern struct task_struct *arch_get_kprobe_task(void *ptr);
111extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs); 107extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs);
112extern void arch_kprobe_flush_task(struct task_struct *tk);
113#else /* ARCH_SUPPORTS_KRETPROBES */ 108#else /* ARCH_SUPPORTS_KRETPROBES */
114static inline void kretprobe_trampoline(void)
115{
116}
117static inline int trampoline_probe_handler(struct kprobe *p,
118 struct pt_regs *regs)
119{
120 return 0;
121}
122static inline void trampoline_post_handler(struct kprobe *p,
123 struct pt_regs *regs, unsigned long flags)
124{
125}
126static inline void arch_prepare_kretprobe(struct kretprobe *rp, 109static inline void arch_prepare_kretprobe(struct kretprobe *rp,
127 struct pt_regs *regs) 110 struct pt_regs *regs)
128{ 111{
129} 112}
130static inline void arch_kprobe_flush_task(struct task_struct *tk)
131{
132}
133#define arch_get_kprobe_task(ptr) ((struct task_struct *)NULL)
134#endif /* ARCH_SUPPORTS_KRETPROBES */ 113#endif /* ARCH_SUPPORTS_KRETPROBES */
135/* 114/*
136 * Function-return probe - 115 * Function-return probe -
@@ -155,8 +134,8 @@ struct kretprobe_instance {
155 struct hlist_node uflist; /* either on free list or used list */ 134 struct hlist_node uflist; /* either on free list or used list */
156 struct hlist_node hlist; 135 struct hlist_node hlist;
157 struct kretprobe *rp; 136 struct kretprobe *rp;
158 void *ret_addr; 137 kprobe_opcode_t *ret_addr;
159 void *stack_addr; 138 struct task_struct *task;
160}; 139};
161 140
162#ifdef CONFIG_KPROBES 141#ifdef CONFIG_KPROBES
@@ -176,6 +155,7 @@ extern void arch_copy_kprobe(struct kprobe *p);
176extern void arch_arm_kprobe(struct kprobe *p); 155extern void arch_arm_kprobe(struct kprobe *p);
177extern void arch_disarm_kprobe(struct kprobe *p); 156extern void arch_disarm_kprobe(struct kprobe *p);
178extern void arch_remove_kprobe(struct kprobe *p); 157extern void arch_remove_kprobe(struct kprobe *p);
158extern int arch_init(void);
179extern void show_registers(struct pt_regs *regs); 159extern void show_registers(struct pt_regs *regs);
180extern kprobe_opcode_t *get_insn_slot(void); 160extern kprobe_opcode_t *get_insn_slot(void);
181extern void free_insn_slot(kprobe_opcode_t *slot); 161extern void free_insn_slot(kprobe_opcode_t *slot);
@@ -196,8 +176,6 @@ int register_kretprobe(struct kretprobe *rp);
196void unregister_kretprobe(struct kretprobe *rp); 176void unregister_kretprobe(struct kretprobe *rp);
197 177
198struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp); 178struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp);
199struct kretprobe_instance *get_rp_inst(void *sara);
200struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk);
201void add_rp_inst(struct kretprobe_instance *ri); 179void add_rp_inst(struct kretprobe_instance *ri);
202void kprobe_flush_task(struct task_struct *tk); 180void kprobe_flush_task(struct task_struct *tk);
203void recycle_rp_inst(struct kretprobe_instance *ri); 181void recycle_rp_inst(struct kretprobe_instance *ri);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 65242529a75f..90c0e82b650c 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -240,12 +240,6 @@ static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
240 return 0; 240 return 0;
241} 241}
242 242
243struct kprobe trampoline_p = {
244 .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
245 .pre_handler = trampoline_probe_handler,
246 .post_handler = trampoline_post_handler
247};
248
249struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp) 243struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
250{ 244{
251 struct hlist_node *node; 245 struct hlist_node *node;
@@ -264,35 +258,18 @@ static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
264 return NULL; 258 return NULL;
265} 259}
266 260
267struct kretprobe_instance *get_rp_inst(void *sara)
268{
269 struct hlist_head *head;
270 struct hlist_node *node;
271 struct task_struct *tsk;
272 struct kretprobe_instance *ri;
273
274 tsk = arch_get_kprobe_task(sara);
275 head = &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
276 hlist_for_each_entry(ri, node, head, hlist) {
277 if (ri->stack_addr == sara)
278 return ri;
279 }
280 return NULL;
281}
282
283void add_rp_inst(struct kretprobe_instance *ri) 261void add_rp_inst(struct kretprobe_instance *ri)
284{ 262{
285 struct task_struct *tsk;
286 /* 263 /*
287 * Remove rp inst off the free list - 264 * Remove rp inst off the free list -
288 * Add it back when probed function returns 265 * Add it back when probed function returns
289 */ 266 */
290 hlist_del(&ri->uflist); 267 hlist_del(&ri->uflist);
291 tsk = arch_get_kprobe_task(ri->stack_addr); 268
292 /* Add rp inst onto table */ 269 /* Add rp inst onto table */
293 INIT_HLIST_NODE(&ri->hlist); 270 INIT_HLIST_NODE(&ri->hlist);
294 hlist_add_head(&ri->hlist, 271 hlist_add_head(&ri->hlist,
295 &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]); 272 &kretprobe_inst_table[hash_ptr(ri->task, KPROBE_HASH_BITS)]);
296 273
297 /* Also add this rp inst to the used list. */ 274 /* Also add this rp inst to the used list. */
298 INIT_HLIST_NODE(&ri->uflist); 275 INIT_HLIST_NODE(&ri->uflist);
@@ -319,34 +296,25 @@ struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
319 return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]; 296 return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
320} 297}
321 298
322struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk)
323{
324 struct task_struct *tsk;
325 struct hlist_head *head;
326 struct hlist_node *node;
327 struct kretprobe_instance *ri;
328
329 head = &kretprobe_inst_table[hash_ptr(tk, KPROBE_HASH_BITS)];
330
331 hlist_for_each_entry(ri, node, head, hlist) {
332 tsk = arch_get_kprobe_task(ri->stack_addr);
333 if (tsk == tk)
334 return ri;
335 }
336 return NULL;
337}
338
339/* 299/*
340 * This function is called from do_exit or do_execv when task tk's stack is 300 * This function is called from exit_thread or flush_thread when task tk's
341 * about to be recycled. Recycle any function-return probe instances 301 * stack is being recycled so that we can recycle any function-return probe
342 * associated with this task. These represent probed functions that have 302 * instances associated with this task. These left over instances represent
343 * been called but may never return. 303 * probed functions that have been called but will never return.
344 */ 304 */
345void kprobe_flush_task(struct task_struct *tk) 305void kprobe_flush_task(struct task_struct *tk)
346{ 306{
307 struct kretprobe_instance *ri;
308 struct hlist_head *head;
309 struct hlist_node *node, *tmp;
347 unsigned long flags = 0; 310 unsigned long flags = 0;
311
348 spin_lock_irqsave(&kprobe_lock, flags); 312 spin_lock_irqsave(&kprobe_lock, flags);
349 arch_kprobe_flush_task(tk); 313 head = kretprobe_inst_table_head(current);
314 hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
315 if (ri->task == tk)
316 recycle_rp_inst(ri);
317 }
350 spin_unlock_irqrestore(&kprobe_lock, flags); 318 spin_unlock_irqrestore(&kprobe_lock, flags);
351} 319}
352 320
@@ -606,9 +574,10 @@ static int __init init_kprobes(void)
606 INIT_HLIST_HEAD(&kretprobe_inst_table[i]); 574 INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
607 } 575 }
608 576
609 err = register_die_notifier(&kprobe_exceptions_nb); 577 err = arch_init();
610 /* Register the trampoline probe for return probe */ 578 if (!err)
611 register_kprobe(&trampoline_p); 579 err = register_die_notifier(&kprobe_exceptions_nb);
580
612 return err; 581 return err;
613} 582}
614 583