[FIX] Move urp disarming from atomic context on mm_release 09/47309/3
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Sun, 30 Aug 2015 13:21:52 +0000 (16:21 +0300)
committerDmitry Kovalenko <d.kovalenko@samsung.com>
Mon, 7 Sep 2015 08:32:55 +0000 (01:32 -0700)
Change-Id: Ia8ff37235b5dfe4d43f8d1578459bb4df444468b
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
uprobe/swap_uprobes.c
uprobe/swap_uprobes.h
us_manager/helper.c

index c5daf1c..f7573d4 100644 (file)
@@ -894,37 +894,6 @@ int swap_register_uretprobe(struct uretprobe *rp)
 EXPORT_SYMBOL_GPL(swap_register_uretprobe);
 
 /**
- * @brief Disarms uretprobes for specified task.
- *
- * @param task Pointer to the task_struct.
- * @return Void.
- */
-void swap_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(KERN_INFO "%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, 0);
-                       recycle_urp_inst(ri);
-               }
-       }
-
-       spin_unlock_irqrestore(&uretprobe_lock, flags);
-}
-EXPORT_SYMBOL_GPL(swap_discard_pending_uretprobes);
-
-/**
  * @brief Unregisters uretprobe.
  *
  * @param rp Pointer to the ureprobe.
@@ -1050,7 +1019,7 @@ static void urinst_info_disarm(struct urinst_info *urinst, struct task_struct *t
        arch_disarm_urp_inst(&ri, task, tramp);
 }
 
-void urinst_info_get_current_hlist(struct hlist_head *head)
+void urinst_info_get_current_hlist(struct hlist_head *head, bool recycle)
 {
        unsigned long flags;
        struct task_struct *task = current;
@@ -1076,6 +1045,8 @@ void urinst_info_get_current_hlist(struct hlist_head *head)
                                last = &urinst->hlist;
                        }
 
+                       if (recycle)
+                               recycle_urp_inst(ri);
                }
        }
        spin_unlock_irqrestore(&uretprobe_lock, flags);
index cbee706..66f165f 100644 (file)
@@ -72,7 +72,7 @@ void uinst_info_destroy(struct uinst_info *uinst);
 void uinst_info_disarm(struct uinst_info *uinst, struct task_struct *task);
 
 
-void urinst_info_get_current_hlist(struct hlist_head *head);
+void urinst_info_get_current_hlist(struct hlist_head *head, bool recycle);
 void urinst_info_put_current_hlist(struct hlist_head *head,
                                  struct task_struct *task);
 
@@ -167,7 +167,6 @@ void swap_unregister_uretprobe(struct uretprobe *rp);
 void __swap_unregister_uretprobe(struct uretprobe *rp, int disarm);
 
 void swap_unregister_all_uprobes(struct task_struct *task);
-void swap_discard_pending_uretprobes(struct task_struct *task);
 
 void swap_ujprobe_return(void);
 struct kprobe *get_ukprobe(void *addr, pid_t tgid);
index 2e71afd..e5eeb2c 100644 (file)
@@ -265,7 +265,7 @@ static void rm_uprobes_child(struct kretprobe_instance *ri,
        proc = sspt_proc_get_by_task(current);
        if (proc) {
                sspt_proc_on_each_ip(proc, func_uinst_creare, (void *)&cdata.head);
-               urinst_info_get_current_hlist(&cdata.rhead);
+               urinst_info_get_current_hlist(&cdata.rhead, false);
        }
        sspt_proc_write_unlock();
 
@@ -390,9 +390,27 @@ static unsigned long mr_cb(void *data)
        struct task_struct *task = *(struct task_struct **)data;
 
        if (task->tgid != task->pid) {
+               struct sspt_proc *proc;
+               struct hlist_head head = HLIST_HEAD_INIT;
+
+               if (task != current) {
+                       pr_err("call mm_release in isn't current context\n");
+                       return 0;
+               }
+
                /* if the thread is killed we need to discard pending
                 * uretprobe instances which have not triggered yet */
-               swap_discard_pending_uretprobes(task);
+               sspt_proc_write_lock();
+               proc = sspt_proc_get_by_task(task);
+               if (proc) {
+                       urinst_info_get_current_hlist(&head, true);
+               }
+               sspt_proc_write_unlock();
+
+               if (proc) {
+                       /* disarm urp for task */
+                       urinst_info_put_current_hlist(&head, task);
+               }
        } else {
                call_mm_release(task);
        }