diff options
author | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2015-08-30 16:21:52 +0300 |
---|---|---|
committer | Dmitry Kovalenko <d.kovalenko@samsung.com> | 2015-09-07 01:32:55 -0700 |
commit | 0031104ca9afac91f827f8330ef278ffb0de411d (patch) | |
tree | 508e8caf75c134f7f8a5c868d06dc9f2530f73e3 | |
parent | 82ae9bb832e8120c532cc22cbf59e1f4602d5ebd (diff) | |
download | swap-modules-0031104ca9afac91f827f8330ef278ffb0de411d.tar.gz swap-modules-0031104ca9afac91f827f8330ef278ffb0de411d.tar.bz2 swap-modules-0031104ca9afac91f827f8330ef278ffb0de411d.zip |
[FIX] Move urp disarming from atomic context on mm_release
Change-Id: Ia8ff37235b5dfe4d43f8d1578459bb4df444468b
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
-rw-r--r-- | uprobe/swap_uprobes.c | 35 | ||||
-rw-r--r-- | uprobe/swap_uprobes.h | 3 | ||||
-rw-r--r-- | us_manager/helper.c | 22 |
3 files changed, 24 insertions, 36 deletions
diff --git a/uprobe/swap_uprobes.c b/uprobe/swap_uprobes.c index c5daf1c0..f7573d4d 100644 --- a/uprobe/swap_uprobes.c +++ b/uprobe/swap_uprobes.c @@ -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); diff --git a/uprobe/swap_uprobes.h b/uprobe/swap_uprobes.h index cbee7068..66f165ff 100644 --- a/uprobe/swap_uprobes.h +++ b/uprobe/swap_uprobes.h @@ -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); diff --git a/us_manager/helper.c b/us_manager/helper.c index 2e71afdf..e5eeb2cb 100644 --- a/us_manager/helper.c +++ b/us_manager/helper.c @@ -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); } |