[FIX] Remove pending uretprobes in mm_release() handler 67/19267/2
authorVasiliy Ulyanov <v.ulyanov@samsung.com>
Wed, 9 Apr 2014 13:49:05 +0000 (17:49 +0400)
committerVasiliy Ulyanov <v.ulyanov@samsung.com>
Wed, 9 Apr 2014 14:39:23 +0000 (18:39 +0400)
Fixed an issue when some uretprobe instances still remain
if the task (thread) is killed by a signal while residing
in the instrumented function.

Change-Id: I4a223e0a7a29c5ca6acfe8b38b65c4ba207fa2f7
Signed-off-by: Vasiliy Ulyanov <v.ulyanov@samsung.com>
uprobe/swap_uprobes.c
uprobe/swap_uprobes.h
us_manager/helper.c

index 3792476..4a43fad 100644 (file)
@@ -779,6 +779,31 @@ int dbi_disarm_urp_inst_for_task(struct task_struct *parent, struct task_struct
 }
 EXPORT_SYMBOL_GPL(dbi_disarm_urp_inst_for_task);
 
+void dbi_discard_pending_uretprobes(struct task_struct *task)
+{
+       unsigned long flags;
+       struct uretprobe_instance *ri;
+       struct hlist_head *head;
+       struct hlist_node *tmp;
+       DECLARE_NODE_PTR_FOR_HLIST(node);
+
+       spin_lock_irqsave(&uretprobe_lock, flags);
+
+       head = uretprobe_inst_table_head(task->mm);
+       swap_hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+               if (ri->task == task) {
+                       printk("%s (%d/%d): pending urp inst: %08lx\n",
+                              task->comm, task->tgid, task->pid,
+                              (unsigned long)ri->rp->up.kp.addr);
+                       arch_disarm_urp_inst(ri, task);
+                       recycle_urp_inst(ri);
+               }
+       }
+
+       spin_unlock_irqrestore(&uretprobe_lock, flags);
+}
+EXPORT_SYMBOL_GPL(dbi_discard_pending_uretprobes);
+
 void __dbi_unregister_uretprobe(struct uretprobe *rp, int disarm)
 {
        unsigned long flags;
index 1d6afbf..c5e0e3d 100644 (file)
@@ -103,6 +103,7 @@ void dbi_unregister_uretprobe(struct uretprobe *rp);
 void __dbi_unregister_uretprobe(struct uretprobe *rp, int disarm);
 
 void dbi_unregister_all_uprobes(struct task_struct *task);
+void dbi_discard_pending_uretprobes(struct task_struct *task);
 
 void swap_ujprobe_return(void);
 struct kprobe *get_ukprobe(void *addr, pid_t tgid);
index c733811..0b27e93 100644 (file)
@@ -198,6 +198,9 @@ static int mr_pre_handler(struct kprobe *p, struct pt_regs *regs)
                goto out;
 
        if (task->tgid != task->pid) {
+               /* if the thread is killed we need to discard pending
+                * uretprobe instances which have not triggered yet */
+               dbi_discard_pending_uretprobes(task);
                goto out;
        }