From c0b0ac2a58b0399b094af710c21626d4ef2bd075 Mon Sep 17 00:00:00 2001 From: Gonzha Dmitriy Evgenevich Date: Mon, 21 Nov 2011 13:15:13 +0400 Subject: [PATCH] Architecture-dependent x86 part updated Accordind to current changes introduced in d46e3a57e37101ec8a9367fbcd6f28c188631a9f 2b5e0bbc4c7cccc18bd47af48f9eb9beb5fa123a for comportability with current architecture-independent part --- kprobe/arch/asm-x86/dbi_kprobes.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/kprobe/arch/asm-x86/dbi_kprobes.c b/kprobe/arch/asm-x86/dbi_kprobes.c index b803ab3..355cf31 100644 --- a/kprobe/arch/asm-x86/dbi_kprobes.c +++ b/kprobe/arch/asm-x86/dbi_kprobes.c @@ -1090,7 +1090,17 @@ int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs) INIT_HLIST_HEAD (&empty_rp); spin_lock_irqsave (&kretprobe_lock, flags); - head = kretprobe_inst_table_head (current); + /* + * We are using different hash keys (current and mm) for finding kernel + * space and user space probes. Kernel space probes can change mm field in + * task_struct. User space probes can be shared between threads of one + * process so they have different current but same mm. + */ + if (p && p->tgid) { + head = kretprobe_inst_table_head(current->mm); + } else { + head = kretprobe_inst_table_head(current); + } if(!p){ // X86 kernel space DBPRINTF ("regs %p", regs); @@ -1170,35 +1180,47 @@ int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs) // if we are not at the end of the list and current retprobe should be disarmed if (node && ri->rp2) { + struct hlist_node *current_node = node; crp = ri->rp2; /*sprintf(die_msg, "deferred disarm p->addr = %p [%lx %lx %lx]\n", crp->kp.addr, *kaddrs[0], *kaddrs[1], *kaddrs[2]); DIE(die_msg, regs); */ // look for other instances for the same retprobe - hlist_for_each_entry_continue (ri, node, hlist) + hlist_for_each_entry_safe (ri, node, tmp, head, hlist) { - if (ri->task != current) - continue; /* another task is sharing our hash bucket */ - if (ri->rp2 == crp) //if instance belong to the same retprobe + /* + * Trying to find another retprobe instance associated with + * the same retprobe. + */ + if (ri->rp2 == crp && node != current_node) break; } if (!node) { // if there are no more instances for this retprobe // delete retprobe DBPRINTF ("defered retprobe deletion p->addr = %p", crp->kp.addr); + /* + If there is no any retprobe instances of this retprobe + we can free the resources related to the probe. + */ + struct kprobe *is_p = &crp->kp; + if (!(hlist_unhashed(&is_p->is_hlist))) { + hlist_del_rcu(&is_p->is_hlist); + } unregister_uprobe (&crp->kp, current, 1); kfree (crp); } + hlist_del(current_node); } } } - spin_unlock_irqrestore (&kretprobe_lock, flags); hlist_for_each_entry_safe (ri, node, tmp, &empty_rp, hlist) { hlist_del (&ri->hlist); kfree (ri); } + spin_unlock_irqrestore (&kretprobe_lock, flags); if(!p) // X86 kernel space return (int)orig_ret_address; -- 2.7.4