Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (un)registration and exception handling.

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Peter Zijlstra
Date: Tuesday, September 7, 2010 - 2:33 am

On Tue, 2010-09-07 at 12:18 +0530, Srikar Dronamraju wrote:

Not if your filter function works.

So let me try this again, (assumes boosted probes):

struct uprobe {
	struct inode	*inode;	/* we hold a ref */
	unsigned long	offset;

	int (*handler)(void); /* arguments.. ? */
	int (*filter)(struct task_struct *);

	int		insn_size;		/* size of */
	char		insn[MAX_INSN_SIZE];	/* the original insn */

	int		ret_addr_offset;	/* return addr offset
						   in the slot */
	char		replacement[SLOT_SIZE]; /* replacement
						   instructions */
	
	atomic_t	ref; /* lifetime muck */
	struct rcu_head	rcu;
};

static struct {
	raw_spinlock_t	tree_lock;
	rb_root		tree;
} uprobes;

static void uprobes_add(struct uprobe *uprobe)
{
	/* add to uprobes.tree, sorted on inode:offset */
}

static void uprobes_del(struct uprobe *uprobe)
{
	/* delete from uprobes.tree */
}

static struct uprobe *
uprobes_find_get(struct address_space *mapping, unsigned long offset)
{
	unsigned long flags;
	struct uprobe *uprobe;

	raw_spin_lock_irqsave(&uprobes.treelock, flags);
	uprobe = find_in_tree(&uprobes.tree);
	if (!atomic_inc_not_zero(&uprobe->ref))
		uprobe = NULL;
	raw_spin_unlock_irqrestore(&uprobes.treelock, flags);

	return uprobe;
}

static void __uprobe_free(struct rcu_head *head)
{
	struct uprobe *uprobe = container_of(head, struct uprobe, rcu);

	kfree(uprobe);
}

static void put_uprobe(struct uprobe *uprobe)
{
	if (atomic_dec_and_test(&uprobe->ref))
		call_rcu(&uprobe->rcu, __uprobe_free);
}

static inline int valid_vma(struct vm_area_struct *vma)
{
	if (!vma->vm_file)
		return 0;

	if (vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED) ==
			    (VM_READ|VM_EXEC))
		return 1;

	return 0;
}

int register_uprobe(struct uprobe *uprobe)
{
	struct vm_area_struct *vma;

	inode_get(uprobe->inode);
	atomic_set(1, &uprobe->ref);

	uprobes_add(uprobe); /* add before the rmap walk, so that 
				new mmap()s will find it too */

	for_each_rmap_vma(vma, uprobe->inode->i_mapping) {
		struct mm_struct *mm = vma->vm_mm;
		int install_probe = 0;

		if (!valid_vma(vma))
			continue;

		for_each_task_in_process(p, mm->owner) {
			if (uprobe->filter(p)) {
				p->has_uprobe = 1;
				install_probe = 1;
			}
		}

		if (install_probe) {
			mm->has_uprobes = 1;
			frob_text(uprobe, mm);
		}
	}
}

void unregister_uprobe(struct uprobe *uprobe)
{
	/* pretty much the same, except restore the original text */
	put_uprobe(uprobe);
}

void uprobe_fork(struct task_struct *child)
{
	struct vm_area_struct *vma;

	if (!child->mm->has_uprobes)	
		return;

	for_each_vma(vma, child->mm) {
		struct uprobe *uprobe;

		if (!valid_vma(vma))
			continue;

		for_each_probe_in_mapping(uprobe, vma->vm_file->f_mapping) {
			if (uprobe->filter(child)) {
				child->has_uprobe = 1;
				return;
			}
		}
	}
}

void uprobe_mmap(struct vm_area_struct *vma)
{
	struct uprobe *uprobe;

	if (!valid_vma(vma))
		return;

	for_each_probe_in_mapping(uprobe, vma->vm_file->f_mapping) {
		int install_probe = 0;

		for_each_task_in_process(p, vma->vm_mm->owner) {
			if (uprobe->filter(p)) {
				p->has_uprobe = 1;
				install_probe = 1;
			}
		}

		if (install_probe) {
			mm->has_uprobes = 1;
			frob_text(uprobe, mm);
		}
	}
}

void uprobe_hit(struct pt_regs *regs)
{
	unsigned long addr = instruction_pointer(regs);
	struct mm_struct *mm = current->mm;
	struct vm_area_struct *vma;
	unsigned long offset;

	down_read(&mm->mmap_sem);
	vma = find_vma(mm, addr);

	if (!valid_vma)
		goto fail;

	offset = addr - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT);

	uprobe = uprobes_find_get(vma->vm_file->f_mapping, offset);
	up_read(&mm->mmap_sem);

	if (!uprobe)
		goto fail;

	if (current->has_uprobe && uprobe->filter(current))
		uprobe->handle();

	ret_addr = addr + uprobe->insn_size;

	cpu = get_cpu()
	slot = get_slot(cpu);
	memcpy(slot, uprobe->replacement, SLOT_SIZE);
	memcpy(slot + uprobe->ret_addr_offset, &ret_addr, sizeof(unsigned
long));
	set_instruction_pointer(regs, uaddr_addr_of(slot));
	put_cpu(); /* preemption notifiers would take it from here */

	put_uprobe(uprobe);
	return;

fail:
	SIGTRAP
}

See, no extra traps, no funny intermediate data structures to manage,
and you get the power of ->filter() to implement whatever policy you
want, including simple process wide things.
--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCHv11 2.6.36-rc2-tip 0/15] 0: Uprobes Patches, Srikar Dronamraju, (Wed Aug 25, 6:41 am)
[PATCHv11 2.6.36-rc2-tip 1/15] 1: mm: Move replace_page() ..., Srikar Dronamraju, (Wed Aug 25, 6:41 am)
[PATCHv11 2.6.36-rc2-tip 2/15] 2: uprobes: Breakpoint ins ..., Srikar Dronamraju, (Wed Aug 25, 6:41 am)
[PATCHv11 2.6.36-rc2-tip 3/15] 3: uprobes: Slot allocatio ..., Srikar Dronamraju, (Wed Aug 25, 6:41 am)
[PATCHv11 2.6.36-rc2-tip 4/15] 4: uprobes: x86 specific f ..., Srikar Dronamraju, (Wed Aug 25, 6:42 am)
[PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (un)re ..., Srikar Dronamraju, (Wed Aug 25, 6:42 am)
[PATCHv11 2.6.36-rc2-tip 6/15] 6: uprobes: X86 support fo ..., Srikar Dronamraju, (Wed Aug 25, 6:42 am)
[PATCHv11 2.6.36-rc2-tip 7/15] 7: uprobes: Uprobes Docume ..., Srikar Dronamraju, (Wed Aug 25, 6:42 am)
[PATCHv11 2.6.36-rc2-tip 8/15] 8: tracing: Extract out co ..., Srikar Dronamraju, (Wed Aug 25, 6:42 am)
[PATCHv11 2.6.36-rc2-tip 9/15] 9: tracing: uprobes trace_ ..., Srikar Dronamraju, (Wed Aug 25, 6:43 am)
[PATCHv11 2.6.36-rc2-tip 10/15] 10: tracing: config option ..., Srikar Dronamraju, (Wed Aug 25, 6:43 am)
[PATCHv11 2.6.36-rc2-tip 11/15] 11: perf: list symbols in ..., Srikar Dronamraju, (Wed Aug 25, 6:43 am)
[PATCHv11 2.6.36-rc2-tip 12/15] 12: perf: show possible pr ..., Srikar Dronamraju, (Wed Aug 25, 6:43 am)
[PATCHv11 2.6.36-rc2-tip 13/15] 13: perf: Loop thro each o ..., Srikar Dronamraju, (Wed Aug 25, 6:43 am)
[PATCHv11 2.6.36-rc2-tip 14/15] 14: perf: perf interface f ..., Srikar Dronamraju, (Wed Aug 25, 6:44 am)
[PATCHv11 2.6.36-rc2-tip 15/15] 15: perf: Show Potential p ..., Srikar Dronamraju, (Wed Aug 25, 6:44 am)
Re: [PATCHv11 2.6.36-rc2-tip 11/15] 11: perf: list symbols ..., Arnaldo Carvalho de Melo, (Wed Aug 25, 4:21 pm)
Re: [PATCHv11 2.6.36-rc2-tip 11/15] 11: perf: list symbols ..., Srikar Dronamraju, (Wed Aug 25, 9:32 pm)
Re: [PATCHv11 2.6.36-rc2-tip 10/15] 10: tracing: config op ..., Masami Hiramatsu, (Wed Aug 25, 11:02 pm)
Re: [PATCHv11 2.6.36-rc2-tip 10/15] 10: tracing: config op ..., Srikar Dronamraju, (Fri Aug 27, 2:31 am)
Re: [PATCHv11 2.6.36-rc2-tip 10/15] 10: tracing: config op ..., Srikar Dronamraju, (Fri Aug 27, 5:17 am)
[PATCHv11a 2.6.36-rc2-tip 10/15] 10: tracing: config optio ..., Srikar Dronamraju, (Fri Aug 27, 7:10 am)
[PATCHv11a 2.6.36-rc2-tip 12/15] 12: perf: show possible p ..., Srikar Dronamraju, (Fri Aug 27, 7:21 am)
[tip:perf/core] perf symbols: List symbols in a dso in asc ..., tip-bot for Srikar D ..., (Mon Aug 30, 1:35 am)
Re: [PATCHv11 2.6.36-rc2-tip 3/15] 3: uprobes: Slot alloc ..., Srikar Dronamraju, (Thu Sep 2, 10:47 am)
Re: [PATCHv11 2.6.36-rc2-tip 3/15] 3: uprobes: Slot alloc ..., Srikar Dronamraju, (Fri Sep 3, 9:40 am)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Srikar Dronamraju, (Fri Sep 3, 9:42 am)
Re: [PATCHv11 2.6.36-rc2-tip 3/15] 3: uprobes: Slot alloc ..., Srikar Dronamraju, (Fri Sep 3, 10:26 am)
Re: [PATCHv11 2.6.36-rc2-tip 4/15] 4: uprobes: x86 specif ..., Srikar Dronamraju, (Fri Sep 3, 10:48 am)
Re: [PATCHv11 2.6.36-rc2-tip 3/15] 3: uprobes: Slot alloc ..., Srikar Dronamraju, (Sun Sep 5, 10:38 pm)
Re: [PATCHv11 2.6.36-rc2-tip 4/15] 4: uprobes: x86 specif ..., Srikar Dronamraju, (Mon Sep 6, 6:44 am)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Srikar Dronamraju, (Mon Sep 6, 10:46 am)
Re: [PATCHv11 2.6.36-rc2-tip 3/15] 3: uprobes: Slot alloc ..., Srikar Dronamraju, (Mon Sep 6, 10:59 am)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Mathieu Desnoyers, (Mon Sep 6, 11:25 am)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Christoph Hellwig, (Mon Sep 6, 1:40 pm)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Christoph Hellwig, (Mon Sep 6, 2:12 pm)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Srikar Dronamraju, (Mon Sep 6, 11:48 pm)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Peter Zijlstra, (Tue Sep 7, 2:33 am)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Srikar Dronamraju, (Tue Sep 7, 4:51 am)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Srikar Dronamraju, (Tue Sep 7, 5:02 am)
Re: [PATCHv11 2.6.36-rc2-tip 5/15] 5: uprobes: Uprobes (u ..., Mathieu Desnoyers, (Tue Sep 7, 9:47 am)
Re: [PATCHv11 2.6.36-rc2-tip 0/15] 0: Uprobes Patches, Christoph Hellwig, (Fri Oct 29, 2:23 am)
Re: [PATCHv11 2.6.36-rc2-tip 0/15] 0: Uprobes Patches, Srikar Dronamraju, (Fri Oct 29, 3:48 am)
Re: [PATCHv11 2.6.36-rc2-tip 0/15] 0: Uprobes Patches, Christoph Hellwig, (Thu Nov 4, 11:45 am)