From 0e9857722ceb46419508d0ba40c1133dd1bf3cfa Mon Sep 17 00:00:00 2001 From: Vasiliy Ulyanov Date: Wed, 9 Apr 2014 17:49:05 +0400 Subject: [PATCH] [FIX] Remove pending uretprobes in mm_release() handler 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 --- uprobe/swap_uprobes.c | 25 +++++++++++++++++++++++++ uprobe/swap_uprobes.h | 1 + us_manager/helper.c | 3 +++ 3 files changed, 29 insertions(+) diff --git a/uprobe/swap_uprobes.c b/uprobe/swap_uprobes.c index 3792476..4a43fad 100644 --- a/uprobe/swap_uprobes.c +++ b/uprobe/swap_uprobes.c @@ -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; diff --git a/uprobe/swap_uprobes.h b/uprobe/swap_uprobes.h index 1d6afbf..c5e0e3d 100644 --- a/uprobe/swap_uprobes.h +++ b/uprobe/swap_uprobes.h @@ -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); diff --git a/us_manager/helper.c b/us_manager/helper.c index c733811..0b27e93 100644 --- a/us_manager/helper.c +++ b/us_manager/helper.c @@ -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; } -- 2.7.4