linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v3 0/6] uprobes: return probe implementation
@ 2013-02-28 11:00 Anton Arapov
  2013-02-28 11:00 ` [RFC PATCH v3 1/6] uretprobes: preparation patch Anton Arapov
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Anton Arapov @ 2013-02-28 11:00 UTC (permalink / raw)
  To: Anton Arapov, Oleg Nesterov, Srikar Dronamraju
  Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
	Ananth N Mavinakayanahalli

Hello,

  RFC v3 uretprobes implementation. I'd be grateful for review.

  These patches extending uprobes by enabling tools, such as perf(trace_event),
set a breakpoint on probed function's return address. 

v3 changes:
  - removed uretprobe_bypass logic, it will be better to send it as
    independent patch
  - unified xol_get_trampoline_slot() and xol_get_insn_slot()
  - protected uprobe with refcounter in prepare_uretprobe()
  - uprobe_register() routine fails now, if neither consumer is set
  - enclosed implementation into 1/6, 6/6 patches -ENOSYS bits

v2 changes:
  - introduced rp_handler(), get rid of return_consumers
  - get rid of uretprobe_[un]register()
  - introduced arch_uretprobe_get_sp()
  - removed uprobe_task->doomed, kill task immediately
  - fix arch_uretprobe_hijack_return_addr()'s returns
  - address the v1 minor issues

integrated patchset:
  http://github.com/arapov/linux-aa/commits/uretprobes_v3

previous implementations:
  RFCv2: https://lkml.org/lkml/2013/1/9/157
  RFCv1: https://lkml.org/lkml/2012/12/21/133

thanks,
Anton

Anton Arapov (6):
  uretprobes: preparation patch
  uretprobes/x86: hijack return address
  uretprobes: generalize xol_get_insn_slot()
  uretprobes: return probe entry, prepare uretprobe
  uretprobes: invoke return probe handlers
  uretprobes: implemented, thus remove -ENOSYS

 arch/x86/include/asm/uprobes.h |   6 +++
 arch/x86/kernel/uprobes.c      |  29 +++++++++++
 include/linux/uprobes.h        |   6 +++
 kernel/events/uprobes.c        | 112 ++++++++++++++++++++++++++++++++++++++---
 4 files changed, 146 insertions(+), 7 deletions(-)

-- 
1.8.1.2

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [RFC PATCH v3 1/6] uretprobes: preparation patch
  2013-02-28 11:00 [RFC PATCH v3 0/6] uprobes: return probe implementation Anton Arapov
@ 2013-02-28 11:00 ` Anton Arapov
  2013-02-28 11:00 ` [RFC PATCH v3 2/6] uretprobes/x86: hijack return address Anton Arapov
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Anton Arapov @ 2013-02-28 11:00 UTC (permalink / raw)
  To: Anton Arapov, Oleg Nesterov, Srikar Dronamraju
  Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
	Ananth N Mavinakayanahalli

  1/6 and 6/6 patches are here to enclose return probes implementation as well
as prohibit uprobe_register() routine with no consumer set.

v3 changes: (the patch is introduced in v3)
  - check whether at least one of the consumer's handlers were set
  - a 'TODO' cap that will be removed once return probes be implemented

Signed-off-by: Anton Arapov <anton@redhat.com>
---
 include/linux/uprobes.h | 1 +
 kernel/events/uprobes.c | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 02b83db..a28bdee 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -46,6 +46,7 @@ enum uprobe_filter_ctx {
 
 struct uprobe_consumer {
 	int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
+	int (*rp_handler)(struct uprobe_consumer *self, struct pt_regs *regs);
 	bool (*filter)(struct uprobe_consumer *self,
 				enum uprobe_filter_ctx ctx,
 				struct mm_struct *mm);
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index a567c8c..d904164 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -828,6 +828,14 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
 	struct uprobe *uprobe;
 	int ret;
 
+	/* Uprobe must have at least one set consumer */
+	if (!uc->handler && !uc->rp_handler)
+		return -EINVAL;
+
+	/* TODO: Implement return probes */
+	if (uc->rp_handler)
+		return -ENOSYS;
+
 	/* Racy, just to catch the obvious mistakes */
 	if (offset > i_size_read(inode))
 		return -EINVAL;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v3 2/6] uretprobes/x86: hijack return address
  2013-02-28 11:00 [RFC PATCH v3 0/6] uprobes: return probe implementation Anton Arapov
  2013-02-28 11:00 ` [RFC PATCH v3 1/6] uretprobes: preparation patch Anton Arapov
@ 2013-02-28 11:00 ` Anton Arapov
  2013-03-01  5:45   ` Ananth N Mavinakayanahalli
  2013-02-28 11:00 ` [RFC PATCH v3 3/6] uretprobes: generalize xol_get_insn_slot() Anton Arapov
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Anton Arapov @ 2013-02-28 11:00 UTC (permalink / raw)
  To: Anton Arapov, Oleg Nesterov, Srikar Dronamraju
  Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
	Ananth N Mavinakayanahalli

  hijack the return address and replace it with a "trampoline"

v2:
  - remove ->doomed flag, kill task immediately

Signed-off-by: Anton Arapov <anton@redhat.com>
---
 arch/x86/include/asm/uprobes.h |  1 +
 arch/x86/kernel/uprobes.c      | 29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index 8ff8be7..c353555 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -55,4 +55,5 @@ extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
 extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
 extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long rp_trampoline_vaddr, struct pt_regs *regs);
 #endif	/* _ASM_UPROBES_H */
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 0ba4cfb..85e2153 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -697,3 +697,32 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 		send_sig(SIGTRAP, current, 0);
 	return ret;
 }
+
+extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long
+		rp_trampoline_vaddr, struct pt_regs *regs)
+{
+	int rasize, ncopied;
+	unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
+
+	rasize = is_ia32_task() ? 4 : 8;
+	ncopied = copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize);
+	if (unlikely(ncopied))
+		return 0;
+
+	/* check whether address has been already hijacked */
+	if (orig_ret_vaddr == rp_trampoline_vaddr)
+		return orig_ret_vaddr;
+
+	ncopied = copy_to_user((void __user *)regs->sp, &rp_trampoline_vaddr, rasize);
+	if (unlikely(ncopied)) {
+		if (ncopied != rasize) {
+			printk(KERN_ERR "uretprobe: return address clobbered: "
+					"pid=%d, %%sp=%#lx, %%ip=%#lx\n",
+					current->pid, regs->sp, regs->ip);
+			/* kill task immediately */
+			send_sig(SIGSEGV, current, 0);
+		}
+	}
+
+	return orig_ret_vaddr;
+}
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v3 3/6] uretprobes: generalize xol_get_insn_slot()
  2013-02-28 11:00 [RFC PATCH v3 0/6] uprobes: return probe implementation Anton Arapov
  2013-02-28 11:00 ` [RFC PATCH v3 1/6] uretprobes: preparation patch Anton Arapov
  2013-02-28 11:00 ` [RFC PATCH v3 2/6] uretprobes/x86: hijack return address Anton Arapov
@ 2013-02-28 11:00 ` Anton Arapov
  2013-02-28 20:01   ` Oleg Nesterov
  2013-02-28 11:00 ` [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe Anton Arapov
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Anton Arapov @ 2013-02-28 11:00 UTC (permalink / raw)
  To: Anton Arapov, Oleg Nesterov, Srikar Dronamraju
  Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
	Ananth N Mavinakayanahalli

  Generalize xol_take_insn_slot() to enable more consumers of the
function, e.g. trampoline implementation for return probes.

  The first time a uprobe with return consumer is hit for a process, a
trampoline slot is obtained in the xol_area and initialized with a
breakpoint instruction. This slot is subsequently used by all
uretprobes.

v3:
 - unified xol_get_insn_slot(), thus get rid of xol_get_trampoline_slot()

Signed-off-by: Anton Arapov <anton@redhat.com>
---
 kernel/events/uprobes.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index d904164..69bf060 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1221,7 +1221,7 @@ static unsigned long xol_take_insn_slot(struct xol_area *area)
  * xol_get_insn_slot - allocate a slot for xol.
  * Returns the allocated slot address or 0.
  */
-static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
+static unsigned long xol_get_insn_slot(unsigned char *insn)
 {
 	struct xol_area *area;
 	unsigned long offset;
@@ -1239,7 +1239,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
 	/* Initialize the slot */
 	offset = xol_vaddr & ~PAGE_MASK;
 	vaddr = kmap_atomic(area->page);
-	memcpy(vaddr + offset, uprobe->arch.insn, MAX_UINSN_BYTES);
+	memcpy(vaddr + offset, insn, MAX_UINSN_BYTES);
 	kunmap_atomic(vaddr);
 	/*
 	 * We probably need flush_icache_user_range() but it needs vma.
@@ -1353,7 +1353,7 @@ pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
 	if (!utask)
 		return -ENOMEM;
 
-	xol_vaddr = xol_get_insn_slot(uprobe);
+	xol_vaddr = xol_get_insn_slot(uprobe->arch.insn);
 	if (!xol_vaddr)
 		return -ENOMEM;
 
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe
  2013-02-28 11:00 [RFC PATCH v3 0/6] uprobes: return probe implementation Anton Arapov
                   ` (2 preceding siblings ...)
  2013-02-28 11:00 ` [RFC PATCH v3 3/6] uretprobes: generalize xol_get_insn_slot() Anton Arapov
@ 2013-02-28 11:00 ` Anton Arapov
  2013-02-28 20:10   ` Oleg Nesterov
                     ` (2 more replies)
  2013-02-28 11:00 ` [RFC PATCH v3 5/6] uretprobes: invoke return probe handlers Anton Arapov
  2013-02-28 11:00 ` [RFC PATCH v3 6/6] uretprobes: implemented, thus remove -ENOSYS Anton Arapov
  5 siblings, 3 replies; 17+ messages in thread
From: Anton Arapov @ 2013-02-28 11:00 UTC (permalink / raw)
  To: Anton Arapov, Oleg Nesterov, Srikar Dronamraju
  Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
	Ananth N Mavinakayanahalli

  When a uprobe with return consumer is hit, prepare_uretprobe function is
invoked. It creates return_instance, hijacks return address and replaces
it with the trampoline.

 N.B. it might be a good idea to introduce get_uprobe() to reflect
put_uprobe() later, but it is not a subject of this patchset.

v3:
 - protected uprobe with refcounter. See atomic_inc in prepare_uretprobe()
and put_uprobe() in a following patch in handle_uretprobe()
v2:
 - get rid of ->return_consumers member from struct uprobe, introduce
rp_handler() in consumer

Signed-off-by: Anton Arapov <anton@redhat.com>
---
 include/linux/uprobes.h |  5 +++++
 kernel/events/uprobes.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index a28bdee..6aaa1ce 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -69,6 +69,10 @@ struct uprobe_task {
 	enum uprobe_task_state		state;
 	struct arch_uprobe_task		autask;
 
+	/*
+	 * list for tracking uprobes with return consumers
+	 */
+	struct hlist_head		return_uprobes;
 	struct uprobe			*active_uprobe;
 
 	unsigned long			xol_vaddr;
@@ -92,6 +96,7 @@ struct xol_area {
 	 * the vma go away, and we must handle that reasonably gracefully.
 	 */
 	unsigned long 		vaddr;		/* Page(s) of instruction slots */
+	unsigned long		rp_trampoline_vaddr; /* trampoline address */
 };
 
 struct uprobes_state {
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 69bf060..57f70cd 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -75,6 +75,12 @@ struct uprobe {
 	struct arch_uprobe	arch;
 };
 
+struct return_uprobe_i {
+	struct uprobe		*uprobe;
+	struct hlist_node	hlist;		/* node in list */
+	unsigned long		orig_ret_vaddr; /* original return address */
+};
+
 /*
  * valid_vma: Verify if the specified vma is an executable vma
  * Relax restrictions while unregistering: vm_flags might have
@@ -1336,11 +1342,48 @@ void uprobe_copy_process(struct task_struct *t)
  */
 static struct uprobe_task *get_utask(void)
 {
-	if (!current->utask)
+	if (!current->utask) {
 		current->utask = kzalloc(sizeof(struct uprobe_task), GFP_KERNEL);
+		if (current->utask)
+			INIT_HLIST_HEAD(&current->utask->return_uprobes);
+	}
 	return current->utask;
 }
 
+static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	struct return_uprobe_i *ri;
+	struct uprobe_task *utask;
+	struct xol_area *area;
+	unsigned long rp_trampoline_vaddr = 0;
+	uprobe_opcode_t insn = UPROBE_SWBP_INSN;
+
+	area = get_xol_area();
+	if (area)
+		rp_trampoline_vaddr = area->rp_trampoline_vaddr;
+	if (!rp_trampoline_vaddr) {
+		rp_trampoline_vaddr = xol_get_insn_slot(&insn);
+		if (!rp_trampoline_vaddr)
+			return;
+	}
+	area->rp_trampoline_vaddr = rp_trampoline_vaddr;
+
+	ri = kzalloc(sizeof(struct return_uprobe_i), GFP_KERNEL);
+	if (!ri)
+		return;
+
+	utask = get_utask();
+	ri->orig_ret_vaddr = arch_uretprobe_hijack_return_addr(rp_trampoline_vaddr, regs);
+	if (likely(ri->orig_ret_vaddr)) {
+		/* TODO: uretprobe bypass logic */
+		atomic_inc(&uprobe->ref);
+		ri->uprobe = uprobe;
+		INIT_HLIST_NODE(&ri->hlist);
+		hlist_add_head(&ri->hlist, &utask->return_uprobes);
+	} else
+		kfree(ri);
+}
+
 /* Prepare to single-step probed instruction out of line. */
 static int
 pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr)
@@ -1494,12 +1537,17 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
 
 static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 {
+	int rc = 0;
 	struct uprobe_consumer *uc;
 	int remove = UPROBE_HANDLER_REMOVE;
 
 	down_read(&uprobe->register_rwsem);
 	for (uc = uprobe->consumers; uc; uc = uc->next) {
-		int rc = uc->handler(uc, regs);
+		if (uc->handler)
+			rc = uc->handler(uc, regs);
+
+		if (uc->rp_handler)
+			prepare_uretprobe(uprobe, regs); /* put bp at return */
 
 		WARN(rc & ~UPROBE_HANDLER_MASK,
 			"bad rc=0x%x from %pf()\n", rc, uc->handler);
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v3 5/6] uretprobes: invoke return probe handlers
  2013-02-28 11:00 [RFC PATCH v3 0/6] uprobes: return probe implementation Anton Arapov
                   ` (3 preceding siblings ...)
  2013-02-28 11:00 ` [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe Anton Arapov
@ 2013-02-28 11:00 ` Anton Arapov
  2013-03-02 18:09   ` Oleg Nesterov
  2013-02-28 11:00 ` [RFC PATCH v3 6/6] uretprobes: implemented, thus remove -ENOSYS Anton Arapov
  5 siblings, 1 reply; 17+ messages in thread
From: Anton Arapov @ 2013-02-28 11:00 UTC (permalink / raw)
  To: Anton Arapov, Oleg Nesterov, Srikar Dronamraju
  Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
	Ananth N Mavinakayanahalli

  Uretprobe handlers are invoked when the trampoline is hit, on completion the
trampoline is replaced with the saved return address and the uretprobe instance
deleted.

v3:
 - protected uprobe with refcounter. See put_uprobe() in handle_uretprobe()
that reflects increment in prepare_uretprobe()
v2:
 - get rid of ->return_consumers member from struct uprobe, introduce
rp_handler() in consumer instead

Signed-off-by: Anton Arapov <anton@redhat.com>
---
 arch/x86/include/asm/uprobes.h |  5 +++++
 kernel/events/uprobes.c        | 50 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index c353555..fa9d9de 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -56,4 +56,9 @@ extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
 extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
 extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long rp_trampoline_vaddr, struct pt_regs *regs);
+
+static inline unsigned long arch_uretprobe_get_sp(struct pt_regs *regs)
+{
+	return (unsigned long)regs->sp;
+}
 #endif	/* _ASM_UPROBES_H */
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 57f70cd..deacb35 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1561,6 +1561,52 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 	up_read(&uprobe->register_rwsem);
 }
 
+static void handler_uretprobe_chain(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	struct uprobe_consumer *uc;
+
+	down_read(&uprobe->register_rwsem);
+	for (uc = uprobe->consumers; uc; uc = uc->next) {
+		if (uc->rp_handler)
+			uc->rp_handler(uc, regs);
+	}
+	up_read(&uprobe->register_rwsem);
+}
+
+static void handle_uretprobe(struct pt_regs *regs)
+{
+	struct hlist_head *head;
+	struct hlist_node *tmp;
+	struct xol_area *area;
+	struct return_uprobe_i *ri;
+	struct uprobe_task *utask;
+
+	/* TODO: uretprobe bypass logic */
+
+	area = get_xol_area();
+	utask = get_utask();
+	head = &utask->return_uprobes;
+	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
+		if (ri->uprobe->consumers) {
+			instruction_pointer_set(regs, ri->orig_ret_vaddr);
+			handler_uretprobe_chain(ri->uprobe, regs);
+		}
+
+		put_uprobe(ri->uprobe);
+		hlist_del(&ri->hlist);
+		kfree(ri);
+
+		if (ri->orig_ret_vaddr != area->rp_trampoline_vaddr)
+			return;
+	}
+
+	/* TODO: change the message */
+	printk(KERN_ERR "uprobe: no instance found! pid/tgid=%d/%d",
+			current->pid, current->tgid);
+	/* TODO: May be sigtrap? if possible to restore utask */
+	send_sig(SIGSEGV, current, 0);
+}
+
 /*
  * Run handler and ask thread to singlestep.
  * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
@@ -1576,8 +1622,8 @@ static void handle_swbp(struct pt_regs *regs)
 
 	if (!uprobe) {
 		if (is_swbp > 0) {
-			/* No matching uprobe; signal SIGTRAP. */
-			send_sig(SIGTRAP, current, 0);
+			/* No matching uprobe; Try with uretprobe */
+			handle_uretprobe(regs);
 		} else {
 			/*
 			 * Either we raced with uprobe_unregister() or we can't
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [RFC PATCH v3 6/6] uretprobes: implemented, thus remove -ENOSYS
  2013-02-28 11:00 [RFC PATCH v3 0/6] uprobes: return probe implementation Anton Arapov
                   ` (4 preceding siblings ...)
  2013-02-28 11:00 ` [RFC PATCH v3 5/6] uretprobes: invoke return probe handlers Anton Arapov
@ 2013-02-28 11:00 ` Anton Arapov
  5 siblings, 0 replies; 17+ messages in thread
From: Anton Arapov @ 2013-02-28 11:00 UTC (permalink / raw)
  To: Anton Arapov, Oleg Nesterov, Srikar Dronamraju
  Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
	Ananth N Mavinakayanahalli

  1/6 and 6/6 patches are here to enclose return probes implementation
as well as prohibit uprobe_register() routine with no consumer set.

v3 changes: (the patch is introduced in v3)
  - remove 'TODO' as return probes implemented now

Signed-off-by: Anton Arapov <anton@redhat.com>
---
 kernel/events/uprobes.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index deacb35..7ae338b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -838,10 +838,6 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
 	if (!uc->handler && !uc->rp_handler)
 		return -EINVAL;
 
-	/* TODO: Implement return probes */
-	if (uc->rp_handler)
-		return -ENOSYS;
-
 	/* Racy, just to catch the obvious mistakes */
 	if (offset > i_size_read(inode))
 		return -EINVAL;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 3/6] uretprobes: generalize xol_get_insn_slot()
  2013-02-28 11:00 ` [RFC PATCH v3 3/6] uretprobes: generalize xol_get_insn_slot() Anton Arapov
@ 2013-02-28 20:01   ` Oleg Nesterov
  0 siblings, 0 replies; 17+ messages in thread
From: Oleg Nesterov @ 2013-02-28 20:01 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar, Ananth N Mavinakayanahalli

Anton, I'll try to read this series asap. Just one note,

On 02/28, Anton Arapov wrote:
>
>   Generalize xol_take_insn_slot() to enable more consumers of the
> function, e.g. trampoline implementation for return probes.

Yes, this is can work too.

But I guess you misunderstood me, or I missed something...

Why do you need xol_area->rp_trampoline_vaddr at all? From the very
beginning I am trying to suggest to use the first slot for trampoline:

	Or. Perhaps even better, do not add this helper at all. xol_alloc_area()
	could reserve the first slot/bit for trampoline. And note that in this
	case we do not need xol_area->rp_trampoline_vaddr, it is always equal
	to xol_area->vaddr.

Doesn't this look simpler?

Oleg.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe
  2013-02-28 11:00 ` [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe Anton Arapov
@ 2013-02-28 20:10   ` Oleg Nesterov
  2013-03-04 14:14     ` Anton Arapov
  2013-03-02 18:26   ` Oleg Nesterov
  2013-03-03 16:40   ` Oleg Nesterov
  2 siblings, 1 reply; 17+ messages in thread
From: Oleg Nesterov @ 2013-02-28 20:10 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar, Ananth N Mavinakayanahalli

On 02/28, Anton Arapov wrote:
>
> +static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs)
> +{
> +	struct return_uprobe_i *ri;
> +	struct uprobe_task *utask;
> +	struct xol_area *area;
> +	unsigned long rp_trampoline_vaddr = 0;
> +	uprobe_opcode_t insn = UPROBE_SWBP_INSN;
> +
> +	area = get_xol_area();
> +	if (area)
> +		rp_trampoline_vaddr = area->rp_trampoline_vaddr;
> +	if (!rp_trampoline_vaddr) {
> +		rp_trampoline_vaddr = xol_get_insn_slot(&insn);
> +		if (!rp_trampoline_vaddr)
> +			return;
> +	}
> +	area->rp_trampoline_vaddr = rp_trampoline_vaddr;

This is called under down_read(), so 2 threads can race with each other
and use the different rp_trampoline_vaddr's if ->rp_trampoline_vaddr was
NULL.

And again, I think ->rp_trampoline_vaddr is simply unneeded, see my
reply to 3/6.

>  static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
>  {
> +	int rc = 0;
>  	struct uprobe_consumer *uc;
>  	int remove = UPROBE_HANDLER_REMOVE;
>  
>  	down_read(&uprobe->register_rwsem);
>  	for (uc = uprobe->consumers; uc; uc = uc->next) {
> -		int rc = uc->handler(uc, regs);
> +		if (uc->handler)
> +			rc = uc->handler(uc, regs);
> +
> +		if (uc->rp_handler)
> +			prepare_uretprobe(uprobe, regs); /* put bp at return */

Hmm. I didn't read this series yet. But at first glance I am not
sure prepare_uretprobe() should be called every time we see
->rp_handler != NULL, there could be multiple consumers...

Oleg.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 2/6] uretprobes/x86: hijack return address
  2013-02-28 11:00 ` [RFC PATCH v3 2/6] uretprobes/x86: hijack return address Anton Arapov
@ 2013-03-01  5:45   ` Ananth N Mavinakayanahalli
  2013-03-01 11:00     ` Anton Arapov
  0 siblings, 1 reply; 17+ messages in thread
From: Ananth N Mavinakayanahalli @ 2013-03-01  5:45 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Oleg Nesterov, Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar

On Thu, Feb 28, 2013 at 12:00:11PM +0100, Anton Arapov wrote:
>   hijack the return address and replace it with a "trampoline"
> 
> v2:
>   - remove ->doomed flag, kill task immediately
> 
> Signed-off-by: Anton Arapov <anton@redhat.com>
> ---
>  arch/x86/include/asm/uprobes.h |  1 +
>  arch/x86/kernel/uprobes.c      | 29 +++++++++++++++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
> index 8ff8be7..c353555 100644
> --- a/arch/x86/include/asm/uprobes.h
> +++ b/arch/x86/include/asm/uprobes.h
> @@ -55,4 +55,5 @@ extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
>  extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
>  extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
>  extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
> +extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long rp_trampoline_vaddr, struct pt_regs *regs);
>  #endif	/* _ASM_UPROBES_H */
> diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
> index 0ba4cfb..85e2153 100644
> --- a/arch/x86/kernel/uprobes.c
> +++ b/arch/x86/kernel/uprobes.c
> @@ -697,3 +697,32 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
>  		send_sig(SIGTRAP, current, 0);
>  	return ret;
>  }
> +
> +extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long
> +		rp_trampoline_vaddr, struct pt_regs *regs)
> +{
> +	int rasize, ncopied;
> +	unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
> +
> +	rasize = is_ia32_task() ? 4 : 8;
> +	ncopied = copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize);
> +	if (unlikely(ncopied))

What if ncopied < rasize? Agreed that the upper order bits can be 0, but should
you not validate ncopied == rasize?

Ananth


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 2/6] uretprobes/x86: hijack return address
  2013-03-01  5:45   ` Ananth N Mavinakayanahalli
@ 2013-03-01 11:00     ` Anton Arapov
  2013-03-01 11:21       ` Ananth N Mavinakayanahalli
  0 siblings, 1 reply; 17+ messages in thread
From: Anton Arapov @ 2013-03-01 11:00 UTC (permalink / raw)
  To: Ananth N Mavinakayanahalli
  Cc: Oleg Nesterov, Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar

On Fri, Mar 01, 2013 at 11:15:36AM +0530, Ananth N Mavinakayanahalli wrote:
> On Thu, Feb 28, 2013 at 12:00:11PM +0100, Anton Arapov wrote:
> >   hijack the return address and replace it with a "trampoline"
> > 
> > v2:
> >   - remove ->doomed flag, kill task immediately
> > 
> > Signed-off-by: Anton Arapov <anton@redhat.com>
> > ---
> >  arch/x86/include/asm/uprobes.h |  1 +
> >  arch/x86/kernel/uprobes.c      | 29 +++++++++++++++++++++++++++++
> >  2 files changed, 30 insertions(+)
> > 
> > diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
> > index 8ff8be7..c353555 100644
> > --- a/arch/x86/include/asm/uprobes.h
> > +++ b/arch/x86/include/asm/uprobes.h
> > @@ -55,4 +55,5 @@ extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
> >  extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
> >  extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
> >  extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
> > +extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long rp_trampoline_vaddr, struct pt_regs *regs);
> >  #endif	/* _ASM_UPROBES_H */
> > diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
> > index 0ba4cfb..85e2153 100644
> > --- a/arch/x86/kernel/uprobes.c
> > +++ b/arch/x86/kernel/uprobes.c
> > @@ -697,3 +697,32 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
> >  		send_sig(SIGTRAP, current, 0);
> >  	return ret;
> >  }
> > +
> > +extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long
> > +		rp_trampoline_vaddr, struct pt_regs *regs)
> > +{
> > +	int rasize, ncopied;
> > +	unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
> > +
> > +	rasize = is_ia32_task() ? 4 : 8;
> > +	ncopied = copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize);
> > +	if (unlikely(ncopied))
> 
> What if ncopied < rasize? Agreed that the upper order bits can be 0, but should
> you not validate ncopied == rasize?

  Function returns 0 in case copy_from_user() was not able to copy
return address entirely, and "if (ncopied)" makes sure of it. We 
can't continue if we have no correct return address.

  copy_from_user() returns number of bytes that were *not* copied,
thus "ncopied == rasize" means copy_from_user() was not able to copy
*all* bytes. I don't see the point of such check here.

  Or am I missing anything?

thank you!
Anton.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 2/6] uretprobes/x86: hijack return address
  2013-03-01 11:00     ` Anton Arapov
@ 2013-03-01 11:21       ` Ananth N Mavinakayanahalli
  0 siblings, 0 replies; 17+ messages in thread
From: Ananth N Mavinakayanahalli @ 2013-03-01 11:21 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Oleg Nesterov, Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar

On Fri, Mar 01, 2013 at 12:00:43PM +0100, Anton Arapov wrote:
> On Fri, Mar 01, 2013 at 11:15:36AM +0530, Ananth N Mavinakayanahalli wrote:
> > On Thu, Feb 28, 2013 at 12:00:11PM +0100, Anton Arapov wrote:

...

> > > +extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long
> > > +		rp_trampoline_vaddr, struct pt_regs *regs)
> > > +{
> > > +	int rasize, ncopied;
> > > +	unsigned long orig_ret_vaddr = 0; /* clear high bits for 32-bit apps */
> > > +
> > > +	rasize = is_ia32_task() ? 4 : 8;
> > > +	ncopied = copy_from_user(&orig_ret_vaddr, (void __user *)regs->sp, rasize);
> > > +	if (unlikely(ncopied))
> > 
> > What if ncopied < rasize? Agreed that the upper order bits can be 0, but should
> > you not validate ncopied == rasize?
> 
>   Function returns 0 in case copy_from_user() was not able to copy
> return address entirely, and "if (ncopied)" makes sure of it. We 
> can't continue if we have no correct return address.
> 
>   copy_from_user() returns number of bytes that were *not* copied,
> thus "ncopied == rasize" means copy_from_user() was not able to copy
> *all* bytes. I don't see the point of such check here.
> 
>   Or am I missing anything?

You are right... my bad.

Ananth


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 5/6] uretprobes: invoke return probe handlers
  2013-02-28 11:00 ` [RFC PATCH v3 5/6] uretprobes: invoke return probe handlers Anton Arapov
@ 2013-03-02 18:09   ` Oleg Nesterov
  0 siblings, 0 replies; 17+ messages in thread
From: Oleg Nesterov @ 2013-03-02 18:09 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar, Ananth N Mavinakayanahalli

On 02/28, Anton Arapov wrote:
>
> @@ -1576,8 +1622,8 @@ static void handle_swbp(struct pt_regs *regs)
>  
>  	if (!uprobe) {
>  		if (is_swbp > 0) {
> -			/* No matching uprobe; signal SIGTRAP. */
> -			send_sig(SIGTRAP, current, 0);
> +			/* No matching uprobe; Try with uretprobe */
> +			handle_uretprobe(regs);

Hmm. at least this looks certainly wrong.

You shifted send_sig(SIGSEGV) into handle_uretprobe(), but if nothing
else printk(KERN_ERR "uprobe: no instance found!") doesn't look nice
if we hit the regular breakoint.

In fact everything handle_uretprobe() does in this case looks wrong.
Including the fact that get_xol_area/get_utask can fail. And unwinding
looks bogus...

I think you need

	if (bp_vaddr == rp_trampoline_vaddr)
		handle_uretprobe()

like the previous version did.

Oleg.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe
  2013-02-28 11:00 ` [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe Anton Arapov
  2013-02-28 20:10   ` Oleg Nesterov
@ 2013-03-02 18:26   ` Oleg Nesterov
  2013-03-03 16:40   ` Oleg Nesterov
  2 siblings, 0 replies; 17+ messages in thread
From: Oleg Nesterov @ 2013-03-02 18:26 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar, Ananth N Mavinakayanahalli

On 02/28, Anton Arapov wrote:
>
> +static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs)
> +{
> +	struct return_uprobe_i *ri;
> +	struct uprobe_task *utask;
> +	struct xol_area *area;
> +	unsigned long rp_trampoline_vaddr = 0;
> +	uprobe_opcode_t insn = UPROBE_SWBP_INSN;
> +
> +	area = get_xol_area();
> +	if (area)
> +		rp_trampoline_vaddr = area->rp_trampoline_vaddr;
> +	if (!rp_trampoline_vaddr) {
> +		rp_trampoline_vaddr = xol_get_insn_slot(&insn);
> +		if (!rp_trampoline_vaddr)
> +			return;
> +	}
> +	area->rp_trampoline_vaddr = rp_trampoline_vaddr;
> +
> +	ri = kzalloc(sizeof(struct return_uprobe_i), GFP_KERNEL);
> +	if (!ri)
> +		return;
> +
> +	utask = get_utask();
> +	ri->orig_ret_vaddr = arch_uretprobe_hijack_return_addr(rp_trampoline_vaddr, regs);
> +	if (likely(ri->orig_ret_vaddr)) {
> +		/* TODO: uretprobe bypass logic */
> +		atomic_inc(&uprobe->ref);

OK, but even this is not enough.

Once we inserted "int3" we must ensure that handle_swbp() will be
called even if this uprobe goes away. We have the reference but it
only protects uprobe itself, it can't protect agains delete_uprobe().

IOW, we must ensure that uprobe_pre_sstep_notifier() can't return 0.

So this patch needs the additional change in find_active_uprobe(),

	-	if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags))
	+	if (!uprobe && hlist_empty(->return_uprobes) &&
	+	    test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags))

Oleg.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe
  2013-02-28 11:00 ` [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe Anton Arapov
  2013-02-28 20:10   ` Oleg Nesterov
  2013-03-02 18:26   ` Oleg Nesterov
@ 2013-03-03 16:40   ` Oleg Nesterov
  2013-03-04 10:49     ` Anton Arapov
  2 siblings, 1 reply; 17+ messages in thread
From: Oleg Nesterov @ 2013-03-03 16:40 UTC (permalink / raw)
  To: Anton Arapov
  Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar, Ananth N Mavinakayanahalli

On 02/28, Anton Arapov wrote:
>
> @@ -69,6 +69,10 @@ struct uprobe_task {
>  	enum uprobe_task_state		state;
>  	struct arch_uprobe_task		autask;
>
> +	/*
> +	 * list for tracking uprobes with return consumers
> +	 */
> +	struct hlist_head		return_uprobes;

Forgot to mention, at least you should also change uprobe_free_utask()
to cleanup this list, the task can exit from inside the ret-probe'd
function(s).

Oleg.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe
  2013-03-03 16:40   ` Oleg Nesterov
@ 2013-03-04 10:49     ` Anton Arapov
  0 siblings, 0 replies; 17+ messages in thread
From: Anton Arapov @ 2013-03-04 10:49 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar, Ananth N Mavinakayanahalli

On Sun, Mar 03, 2013 at 05:40:29PM +0100, Oleg Nesterov wrote:
> On 02/28, Anton Arapov wrote:
> >
> > @@ -69,6 +69,10 @@ struct uprobe_task {
> >  	enum uprobe_task_state		state;
> >  	struct arch_uprobe_task		autask;
> >
> > +	/*
> > +	 * list for tracking uprobes with return consumers
> > +	 */
> > +	struct hlist_head		return_uprobes;
> 
> Forgot to mention, at least you should also change uprobe_free_utask()
> to cleanup this list, the task can exit from inside the ret-probe'd
> function(s).

Yes, right. Thanks for the other mails as well. I will fix it for the
next RFC v4.

Anton.

> Oleg.
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe
  2013-02-28 20:10   ` Oleg Nesterov
@ 2013-03-04 14:14     ` Anton Arapov
  0 siblings, 0 replies; 17+ messages in thread
From: Anton Arapov @ 2013-03-04 14:14 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler,
	Peter Zijlstra, Ingo Molnar, Ananth N Mavinakayanahalli

On Thu, Feb 28, 2013 at 09:10:24PM +0100, Oleg Nesterov wrote:
> On 02/28, Anton Arapov wrote:
> >
> > +static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs)
> > +{
> > +	struct return_uprobe_i *ri;
> > +	struct uprobe_task *utask;
> > +	struct xol_area *area;
> > +	unsigned long rp_trampoline_vaddr = 0;
> > +	uprobe_opcode_t insn = UPROBE_SWBP_INSN;
> > +
> > +	area = get_xol_area();
> > +	if (area)
> > +		rp_trampoline_vaddr = area->rp_trampoline_vaddr;
> > +	if (!rp_trampoline_vaddr) {
> > +		rp_trampoline_vaddr = xol_get_insn_slot(&insn);
> > +		if (!rp_trampoline_vaddr)
> > +			return;
> > +	}
> > +	area->rp_trampoline_vaddr = rp_trampoline_vaddr;
> 
> This is called under down_read(), so 2 threads can race with each other
> and use the different rp_trampoline_vaddr's if ->rp_trampoline_vaddr was
> NULL.
> And again, I think ->rp_trampoline_vaddr is simply unneeded, see my
> reply to 3/6.
  Yes, 'fixed' this, I will send quirky v4 in a few, to maintain your attention. :)

> 
> >  static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
> >  {
> > +	int rc = 0;
> >  	struct uprobe_consumer *uc;
> >  	int remove = UPROBE_HANDLER_REMOVE;
> >  
> >  	down_read(&uprobe->register_rwsem);
> >  	for (uc = uprobe->consumers; uc; uc = uc->next) {
> > -		int rc = uc->handler(uc, regs);
> > +		if (uc->handler)
> > +			rc = uc->handler(uc, regs);
> > +
> > +		if (uc->rp_handler)
> > +			prepare_uretprobe(uprobe, regs); /* put bp at return */
> 
> Hmm. I didn't read this series yet. But at first glance I am not
> sure prepare_uretprobe() should be called every time we see
> ->rp_handler != NULL, there could be multiple consumers...

  I can not come up with a better idea yet, that would narrow down the
number of prepare_uretprobe() calls. 

Anton.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2013-03-04 14:25 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-28 11:00 [RFC PATCH v3 0/6] uprobes: return probe implementation Anton Arapov
2013-02-28 11:00 ` [RFC PATCH v3 1/6] uretprobes: preparation patch Anton Arapov
2013-02-28 11:00 ` [RFC PATCH v3 2/6] uretprobes/x86: hijack return address Anton Arapov
2013-03-01  5:45   ` Ananth N Mavinakayanahalli
2013-03-01 11:00     ` Anton Arapov
2013-03-01 11:21       ` Ananth N Mavinakayanahalli
2013-02-28 11:00 ` [RFC PATCH v3 3/6] uretprobes: generalize xol_get_insn_slot() Anton Arapov
2013-02-28 20:01   ` Oleg Nesterov
2013-02-28 11:00 ` [RFC PATCH v3 4/6] uretprobes: return probe entry, prepare uretprobe Anton Arapov
2013-02-28 20:10   ` Oleg Nesterov
2013-03-04 14:14     ` Anton Arapov
2013-03-02 18:26   ` Oleg Nesterov
2013-03-03 16:40   ` Oleg Nesterov
2013-03-04 10:49     ` Anton Arapov
2013-02-28 11:00 ` [RFC PATCH v3 5/6] uretprobes: invoke return probe handlers Anton Arapov
2013-03-02 18:09   ` Oleg Nesterov
2013-02-28 11:00 ` [RFC PATCH v3 6/6] uretprobes: implemented, thus remove -ENOSYS Anton Arapov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).