summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2015-08-30 16:21:52 +0300
committerDmitry Kovalenko <d.kovalenko@samsung.com>2015-09-07 01:32:55 -0700
commit0031104ca9afac91f827f8330ef278ffb0de411d (patch)
tree508e8caf75c134f7f8a5c868d06dc9f2530f73e3
parent82ae9bb832e8120c532cc22cbf59e1f4602d5ebd (diff)
downloadswap-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.c35
-rw-r--r--uprobe/swap_uprobes.h3
-rw-r--r--us_manager/helper.c22
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);
}