diff options
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r-- | kernel/kprobes.c | 69 |
1 files changed, 19 insertions, 50 deletions
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 | ||
243 | struct kprobe trampoline_p = { | ||
244 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, | ||
245 | .pre_handler = trampoline_probe_handler, | ||
246 | .post_handler = trampoline_post_handler | ||
247 | }; | ||
248 | |||
249 | struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp) | 243 | struct 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 | ||
267 | struct 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 | |||
283 | void add_rp_inst(struct kretprobe_instance *ri) | 261 | void 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 | ||
322 | struct 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 | */ |
345 | void kprobe_flush_task(struct task_struct *tk) | 305 | void 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 | ||