summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2015-08-24 19:00:20 +0300
committerDmitry Kovalenko <d.kovalenko@samsung.com>2015-08-27 23:23:03 -0700
commitee910feead1ca57f9b39949c64fc5573664ef573 (patch)
tree6bdf5f46c4da749411a252bd8833242a2aae9ab7
parent2660ab3be63007ee996c9b40f1ff96599ffd363b (diff)
downloadswap-modules-ee910feead1ca57f9b39949c64fc5573664ef573.tar.gz
swap-modules-ee910feead1ca57f9b39949c64fc5573664ef573.tar.bz2
swap-modules-ee910feead1ca57f9b39949c64fc5573664ef573.zip
[FIX] Flush kretprobe instances after last put_task
Remove rp_inst from kretprobe_inst_table when task has died Change-Id: I97e8b7209e22f70c5c8ff3afc55704aa3ddfa87e Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
-rw-r--r--kprobe/swap_kprobes.c55
1 files changed, 54 insertions, 1 deletions
diff --git a/kprobe/swap_kprobes.c b/kprobe/swap_kprobes.c
index d080dd5b..ece1f7f8 100644
--- a/kprobe/swap_kprobes.c
+++ b/kprobe/swap_kprobes.c
@@ -1091,6 +1091,41 @@ static int swap_disarm_krp_inst(struct kretprobe_instance *ri)
return retval;
}
+static void krp_inst_flush(struct task_struct *task)
+{
+ unsigned long flags;
+ struct kretprobe_instance *ri;
+ struct hlist_node *tmp;
+ struct hlist_head *head;
+ DECLARE_NODE_PTR_FOR_HLIST(node);
+
+ spin_lock_irqsave(&kretprobe_lock, flags);
+ head = kretprobe_inst_table_head(task);
+ swap_hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+ if (ri->task == task) {
+ printk("task[%u %u %s]: flush krp_inst, ret_addr=%p\n",
+ task->tgid, task->pid, task->comm,
+ ri->ret_addr);
+ recycle_rp_inst(ri);
+ }
+ }
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
+}
+
+static int put_task_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct task_struct *t = (struct task_struct *)swap_get_karg(regs, 0);
+
+ /* task has died */
+ krp_inst_flush(t);
+
+ return 0;
+}
+
+static struct kprobe put_task_kp = {
+ .pre_handler = put_task_handler,
+};
+
static int init_module_deps(void)
{
int ret;
@@ -1131,6 +1166,11 @@ static int once(void)
if (module_alloc == NULL)
goto not_found;
+ sym = "__put_task_struct";
+ put_task_kp.addr = (void *)swap_ksyms(sym);
+ if (put_task_kp.addr == NULL)
+ goto not_found;
+
ret = init_module_deps();
if (ret)
return ret;
@@ -1153,14 +1193,27 @@ not_found:
static int init_kprobes(void)
{
+ int ret;
+
init_sm();
atomic_set(&kprobe_count, 0);
- return swap_arch_init_kprobes();
+ ret = swap_arch_init_kprobes();
+ if (ret)
+ return ret;
+
+ ret = swap_register_kprobe(&put_task_kp);
+ if (ret) {
+ swap_arch_exit_kprobes();
+ return ret;
+ }
+
+ return 0;
}
static void exit_kprobes(void)
{
+ swap_unregister_kprobe(&put_task_kp);
swap_arch_exit_kprobes();
exit_sm();
}