* [RFC PATCH v2 0/4] uprobes: return probe implementation
@ 2013-01-09 11:24 Anton Arapov
2013-01-09 11:24 ` [RFC PATCH v2 1/4] uretprobes/x86: hijack return address Anton Arapov
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Anton Arapov @ 2013-01-09 11:24 UTC (permalink / raw)
To: Oleg Nesterov, Srikar Dronamraju
Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
Ananth N Mavinakayanahalli, Anton Arapov
There are RFC uretprobes implementation. I'd be grateful for review.
RFCv1: https://lkml.org/lkml/2012/12/21/133
I've intentionally removed the retprobe bypass logic, it requires
a bit more work.
not fixed since last prior RFC review:
unify xol_get_trampoline_slot() and xol_take_insn_slot()
protect uprobe in prepare_uretprobe()
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
thanks,
Anton Arapov (5):
uretprobes/x86: hijack return address
uretprobes: trampoline implementation
uretprobes: return probe entry, prepare uretprobe
uretprobes: invoke return probe handlers
arch/x86/include/asm/uprobes.h | 6 ++
arch/x86/kernel/uprobes.c | 48 +++++++++++
include/linux/uprobes.h | 9 ++
kernel/events/uprobes.c | 181 ++++++++++++++++++++++++++++++++++++++++-
4 files changed, 241 insertions(+), 3 deletions(-)
--
1.8.0.2
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH v2 1/4] uretprobes/x86: hijack return address
2013-01-09 11:24 [RFC PATCH v2 0/4] uprobes: return probe implementation Anton Arapov
@ 2013-01-09 11:24 ` Anton Arapov
2013-01-09 11:24 ` [RFC PATCH v2 2/4] uretprobes: trampoline implementation Anton Arapov
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Anton Arapov @ 2013-01-09 11:24 UTC (permalink / raw)
To: Oleg Nesterov, Srikar Dronamraju
Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
Ananth N Mavinakayanahalli, Anton Arapov
Function to hijack the return address, replace it with a "trampoline"
and function to predict the stack pointer address value at return.
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.0.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 2/4] uretprobes: trampoline implementation
2013-01-09 11:24 [RFC PATCH v2 0/4] uprobes: return probe implementation Anton Arapov
2013-01-09 11:24 ` [RFC PATCH v2 1/4] uretprobes/x86: hijack return address Anton Arapov
@ 2013-01-09 11:24 ` Anton Arapov
2013-01-09 16:13 ` Oleg Nesterov
2013-01-09 11:24 ` [RFC PATCH v2 3/4] uretprobes: return probe entry, prepare uretprobe Anton Arapov
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Anton Arapov @ 2013-01-09 11:24 UTC (permalink / raw)
To: Oleg Nesterov, Srikar Dronamraju
Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
Ananth N Mavinakayanahalli, Anton Arapov
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.
todo:
unify with xol_take_insn_slot()
Signed-off-by: Anton Arapov <anton@redhat.com>
---
include/linux/uprobes.h | 1 +
kernel/events/uprobes.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 95d0002..bddfad6 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -91,6 +91,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; /* address of trampolines */
};
struct uprobes_state {
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 473db3f..0ad2ac3 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1208,6 +1208,39 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
return xol_vaddr;
}
+/*
+ * xol_get_trampoline_slot - A trampoline slot is obtained the first
+ * time a uprobe with return consumer is hit for a process. Use one
+ * trampoline slot for all probes pertaining to a process, i.e.
+ * one per xol_area.
+ */
+static unsigned long xol_get_trampoline_slot(void)
+{
+ struct xol_area *area;
+ unsigned long offset;
+ uprobe_opcode_t bp_insn = UPROBE_SWBP_INSN;
+ void *vaddr;
+
+ area = get_xol_area();
+ if (!area)
+ return 0;
+
+ if (!area->rp_trampoline_vaddr)
+ area->rp_trampoline_vaddr = xol_take_insn_slot(area);
+
+ if (unlikely(!area->rp_trampoline_vaddr))
+ return 0;
+
+ offset = area->rp_trampoline_vaddr & ~PAGE_MASK;
+ vaddr = kmap_atomic(area->page);
+ memcpy(vaddr + offset, &bp_insn, UPROBE_SWBP_INSN_SIZE);
+ kunmap_atomic(vaddr);
+
+ flush_dcache_page(area->page);
+
+ return area->rp_trampoline_vaddr;
+}
+
/*
* xol_free_insn_slot - If slot was earlier allocated by
* @xol_get_insn_slot(), make the slot available for
--
1.8.0.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 3/4] uretprobes: return probe entry, prepare uretprobe
2013-01-09 11:24 [RFC PATCH v2 0/4] uprobes: return probe implementation Anton Arapov
2013-01-09 11:24 ` [RFC PATCH v2 1/4] uretprobes/x86: hijack return address Anton Arapov
2013-01-09 11:24 ` [RFC PATCH v2 2/4] uretprobes: trampoline implementation Anton Arapov
@ 2013-01-09 11:24 ` Anton Arapov
2013-01-09 16:17 ` Oleg Nesterov
2013-01-09 11:24 ` [RFC PATCH v2 4/4] uretprobes: invoke return probe handlers Anton Arapov
2013-01-09 16:12 ` [RFC PATCH v2 0/4] uprobes: return probe implementation Oleg Nesterov
4 siblings, 1 reply; 11+ messages in thread
From: Anton Arapov @ 2013-01-09 11:24 UTC (permalink / raw)
To: Oleg Nesterov, Srikar Dronamraju
Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
Ananth N Mavinakayanahalli, Anton Arapov
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.
v2:
get rid of ->return_consumers
todo:
protect uprobe
Signed-off-by: Anton Arapov <anton@redhat.com>
---
include/linux/uprobes.h | 4 ++++
kernel/events/uprobes.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index bddfad6..cdc4d53 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -68,6 +68,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;
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 0ad2ac3..d6fa497 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -74,6 +74,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
@@ -1327,11 +1333,44 @@ 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);
+ INIT_HLIST_HEAD(¤t->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;
+
+ area = get_xol_area();
+ if (area)
+ rp_trampoline_vaddr = area->rp_trampoline_vaddr;
+ if (!rp_trampoline_vaddr) {
+ rp_trampoline_vaddr = xol_get_trampoline_slot();
+ if (!rp_trampoline_vaddr)
+ return;
+ }
+
+ ri = (struct return_uprobe_i *)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)) {
+ 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)
@@ -1485,12 +1524,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.0.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v2 4/4] uretprobes: invoke return probe handlers
2013-01-09 11:24 [RFC PATCH v2 0/4] uprobes: return probe implementation Anton Arapov
` (2 preceding siblings ...)
2013-01-09 11:24 ` [RFC PATCH v2 3/4] uretprobes: return probe entry, prepare uretprobe Anton Arapov
@ 2013-01-09 11:24 ` Anton Arapov
2013-01-09 16:28 ` Oleg Nesterov
2013-01-09 16:12 ` [RFC PATCH v2 0/4] uprobes: return probe implementation Oleg Nesterov
4 siblings, 1 reply; 11+ messages in thread
From: Anton Arapov @ 2013-01-09 11:24 UTC (permalink / raw)
To: Oleg Nesterov, Srikar Dronamraju
Cc: LKML, Josh Stone, Frank Eigler, Peter Zijlstra, Ingo Molnar,
Ananth N Mavinakayanahalli, Anton Arapov
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.
v2:
get rid of ->return_consumers
use rp_handler()
Signed-off-by: Anton Arapov <anton@redhat.com>
---
arch/x86/include/asm/uprobes.h | 5 ++++
include/linux/uprobes.h | 4 +++
kernel/events/uprobes.c | 61 +++++++++++++++++++++++++++++++++++++++++-
3 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index c353555..9a605b8 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/include/linux/uprobes.h b/include/linux/uprobes.h
index cdc4d53..1a229db 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -45,7 +45,11 @@ enum uprobe_filter_ctx {
};
struct uprobe_consumer {
+ /* probe handler */
int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
+ /* return probe handler */
+ 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 d6fa497..8232c29 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1548,6 +1548,57 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
up_read(&uprobe->register_rwsem);
}
+static void handler_rp_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_rp_swbp(struct pt_regs *regs)
+{
+ struct hlist_head *head;
+ struct hlist_node *r1, *r2;
+
+ struct return_uprobe_i *ri;
+ struct uprobe_task *utask;
+
+ struct xol_area *area;
+ unsigned long rp_trampoline_vaddr;
+ unsigned long orig_ret_vaddr, cur_sp;
+
+ cur_sp = arch_uretprobe_get_sp(regs);
+ utask = current->utask;
+ head = &utask->return_uprobes;
+
+ area = get_xol_area();
+ rp_trampoline_vaddr = area->vaddr;
+
+ hlist_for_each_entry_safe(ri, r1, r2, head, hlist) {
+ orig_ret_vaddr = ri->orig_ret_vaddr;
+
+ if (ri->uprobe->consumers) {
+ instruction_pointer_set(regs, orig_ret_vaddr);
+ handler_rp_chain(ri->uprobe, regs);
+ }
+
+ hlist_del(&ri->hlist);
+ kfree(ri);
+
+ if (orig_ret_vaddr != rp_trampoline_vaddr)
+ return;
+ }
+
+ printk(KERN_ERR "uretprobe: no instance with original return address!"
+ " pid/tgid=%d/%d", current->pid, current->tgid);
+ send_sig(SIGSEGV, current, 0);
+}
+
/*
* Run handler and ask thread to singlestep.
* Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
@@ -1555,12 +1606,20 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
static void handle_swbp(struct pt_regs *regs)
{
struct uprobe *uprobe;
+ struct xol_area *area;
unsigned long bp_vaddr;
int uninitialized_var(is_swbp);
bp_vaddr = uprobe_get_swbp_addr(regs);
- uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
+ area = get_xol_area();
+ if (area) {
+ if (bp_vaddr == area->vaddr) {
+ handle_rp_swbp(regs);
+ return;
+ }
+ }
+ uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
if (!uprobe) {
if (is_swbp > 0) {
/* No matching uprobe; signal SIGTRAP. */
--
1.8.0.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v2 0/4] uprobes: return probe implementation
2013-01-09 11:24 [RFC PATCH v2 0/4] uprobes: return probe implementation Anton Arapov
` (3 preceding siblings ...)
2013-01-09 11:24 ` [RFC PATCH v2 4/4] uretprobes: invoke return probe handlers Anton Arapov
@ 2013-01-09 16:12 ` Oleg Nesterov
4 siblings, 0 replies; 11+ messages in thread
From: Oleg Nesterov @ 2013-01-09 16:12 UTC (permalink / raw)
To: Anton Arapov
Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler, Peter Zijlstra,
Ingo Molnar, Ananth N Mavinakayanahalli
On 01/09, Anton Arapov wrote:
>
> There are RFC uretprobes implementation. I'd be grateful for review.
>
> RFCv1: https://lkml.org/lkml/2012/12/21/133
>
> I've intentionally removed the retprobe bypass logic, it requires
> a bit more work.
Yes, this is not trivial, lets do this separately.
> not fixed since last prior RFC review:
> unify xol_get_trampoline_slot() and xol_take_insn_slot()
This was of the reasons for "Do not play with utask in xol_get_insn_slot()"
I sent. After this patch you only need the trivial change
- static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
+ static unsigned long xol_get_insn_slot(unsigned char *insn)
and now you do not need xol_get_trampoline_slot().
However. Why do you need it at all? Let me quote myself:
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.
?
> protect uprobe in prepare_uretprobe()
This should be fixed ;)
Oleg.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v2 2/4] uretprobes: trampoline implementation
2013-01-09 11:24 ` [RFC PATCH v2 2/4] uretprobes: trampoline implementation Anton Arapov
@ 2013-01-09 16:13 ` Oleg Nesterov
0 siblings, 0 replies; 11+ messages in thread
From: Oleg Nesterov @ 2013-01-09 16:13 UTC (permalink / raw)
To: Anton Arapov
Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler, Peter Zijlstra,
Ingo Molnar, Ananth N Mavinakayanahalli
On 01/09, Anton Arapov wrote:
>
> 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.
See my reply to 0/4, I think we do not really need this.
> todo:
> unify with xol_take_insn_slot()
>
> Signed-off-by: Anton Arapov <anton@redhat.com>
> ---
> include/linux/uprobes.h | 1 +
> kernel/events/uprobes.c | 33 +++++++++++++++++++++++++++++++++
> 2 files changed, 34 insertions(+)
>
> diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
> index 95d0002..bddfad6 100644
> --- a/include/linux/uprobes.h
> +++ b/include/linux/uprobes.h
> @@ -91,6 +91,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; /* address of trampolines */
> };
>
> struct uprobes_state {
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index 473db3f..0ad2ac3 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -1208,6 +1208,39 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
> return xol_vaddr;
> }
>
> +/*
> + * xol_get_trampoline_slot - A trampoline slot is obtained the first
> + * time a uprobe with return consumer is hit for a process. Use one
> + * trampoline slot for all probes pertaining to a process, i.e.
> + * one per xol_area.
> + */
> +static unsigned long xol_get_trampoline_slot(void)
> +{
> + struct xol_area *area;
> + unsigned long offset;
> + uprobe_opcode_t bp_insn = UPROBE_SWBP_INSN;
> + void *vaddr;
> +
> + area = get_xol_area();
> + if (!area)
> + return 0;
> +
> + if (!area->rp_trampoline_vaddr)
> + area->rp_trampoline_vaddr = xol_take_insn_slot(area);
> +
> + if (unlikely(!area->rp_trampoline_vaddr))
> + return 0;
> +
> + offset = area->rp_trampoline_vaddr & ~PAGE_MASK;
> + vaddr = kmap_atomic(area->page);
> + memcpy(vaddr + offset, &bp_insn, UPROBE_SWBP_INSN_SIZE);
> + kunmap_atomic(vaddr);
> +
> + flush_dcache_page(area->page);
> +
> + return area->rp_trampoline_vaddr;
> +}
> +
> /*
> * xol_free_insn_slot - If slot was earlier allocated by
> * @xol_get_insn_slot(), make the slot available for
> --
> 1.8.0.2
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v2 3/4] uretprobes: return probe entry, prepare uretprobe
2013-01-09 11:24 ` [RFC PATCH v2 3/4] uretprobes: return probe entry, prepare uretprobe Anton Arapov
@ 2013-01-09 16:17 ` Oleg Nesterov
2013-01-10 11:44 ` Anton Arapov
0 siblings, 1 reply; 11+ messages in thread
From: Oleg Nesterov @ 2013-01-09 16:17 UTC (permalink / raw)
To: Anton Arapov
Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler, Peter Zijlstra,
Ingo Molnar, Ananth N Mavinakayanahalli
On 01/09, Anton Arapov wrote:
>
> todo:
> protect uprobe
Yep ;)
> static struct uprobe_task *get_utask(void)
> {
> - if (!current->utask)
> + if (!current->utask) {
> current->utask = kzalloc(sizeof(struct uprobe_task), GFP_KERNEL);
> + INIT_HLIST_HEAD(¤t->utask->return_uprobes);
What if kzalloc() fails?
> +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;
> +
> + area = get_xol_area();
> + if (area)
> + rp_trampoline_vaddr = area->rp_trampoline_vaddr;
> + if (!rp_trampoline_vaddr) {
> + rp_trampoline_vaddr = xol_get_trampoline_slot();
This is obviously racy. But again, so far I think we can simply remove
this.
> 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 */
This doesn't look right. prepare_uretprobe() should not be called
multiple times.
Oleg.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v2 4/4] uretprobes: invoke return probe handlers
2013-01-09 11:24 ` [RFC PATCH v2 4/4] uretprobes: invoke return probe handlers Anton Arapov
@ 2013-01-09 16:28 ` Oleg Nesterov
2013-01-10 11:42 ` Anton Arapov
0 siblings, 1 reply; 11+ messages in thread
From: Oleg Nesterov @ 2013-01-09 16:28 UTC (permalink / raw)
To: Anton Arapov
Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler, Peter Zijlstra,
Ingo Molnar, Ananth N Mavinakayanahalli
On 01/09, Anton Arapov wrote:
>
> static void handle_swbp(struct pt_regs *regs)
> {
> struct uprobe *uprobe;
> + struct xol_area *area;
> unsigned long bp_vaddr;
> int uninitialized_var(is_swbp);
>
> bp_vaddr = uprobe_get_swbp_addr(regs);
> - uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
> + area = get_xol_area();
No, we do not need to allocate xol area here.
> + if (area) {
> + if (bp_vaddr == area->vaddr) {
> + handle_rp_swbp(regs);
Can't understand... this should check bp_vaddr == rp_trampoline_vaddr ?
Again, unless you remove rp_trampoline_vaddr altogether.
Oleg.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v2 4/4] uretprobes: invoke return probe handlers
2013-01-09 16:28 ` Oleg Nesterov
@ 2013-01-10 11:42 ` Anton Arapov
0 siblings, 0 replies; 11+ messages in thread
From: Anton Arapov @ 2013-01-10 11:42 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler, Peter Zijlstra,
Ingo Molnar, Ananth N Mavinakayanahalli
On Wed, Jan 09, 2013 at 05:28:42PM +0100, Oleg Nesterov wrote:
> On 01/09, Anton Arapov wrote:
> >
> > static void handle_swbp(struct pt_regs *regs)
> > {
> > struct uprobe *uprobe;
> > + struct xol_area *area;
> > unsigned long bp_vaddr;
> > int uninitialized_var(is_swbp);
> >
> > bp_vaddr = uprobe_get_swbp_addr(regs);
> > - uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
> > + area = get_xol_area();
>
> No, we do not need to allocate xol area here.
>
> > + if (area) {
> > + if (bp_vaddr == area->vaddr) {
> > + handle_rp_swbp(regs);
>
> Can't understand... this should check bp_vaddr == rp_trampoline_vaddr ?
>
> Again, unless you remove rp_trampoline_vaddr altogether.
yeah, forgot to correct this chunk before I sent it here. I was working on
xol_get_trampoline_slot removal as you suggested.
thanks for valuable comments, seems you are okay with approach to add
rp_handler into uprobe_consumer struct.
Anton.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v2 3/4] uretprobes: return probe entry, prepare uretprobe
2013-01-09 16:17 ` Oleg Nesterov
@ 2013-01-10 11:44 ` Anton Arapov
0 siblings, 0 replies; 11+ messages in thread
From: Anton Arapov @ 2013-01-10 11:44 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Srikar Dronamraju, LKML, Josh Stone, Frank Eigler, Peter Zijlstra,
Ingo Molnar, Ananth N Mavinakayanahalli
On Wed, Jan 09, 2013 at 05:17:01PM +0100, Oleg Nesterov wrote:
> On 01/09, Anton Arapov wrote:
> >
> > todo:
> > protect uprobe
>
> Yep ;)
>
> > static struct uprobe_task *get_utask(void)
> > {
> > - if (!current->utask)
> > + if (!current->utask) {
> > current->utask = kzalloc(sizeof(struct uprobe_task), GFP_KERNEL);
> > + INIT_HLIST_HEAD(¤t->utask->return_uprobes);
>
> What if kzalloc() fails?
:)
>
> > +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;
> > +
> > + area = get_xol_area();
> > + if (area)
> > + rp_trampoline_vaddr = area->rp_trampoline_vaddr;
> > + if (!rp_trampoline_vaddr) {
> > + rp_trampoline_vaddr = xol_get_trampoline_slot();
>
> This is obviously racy. But again, so far I think we can simply remove
> this.
working on this...
> > 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 */
>
> This doesn't look right. prepare_uretprobe() should not be called
> multiple times.
Overlooked this issue, thanks for catching.
Anton.
>
> Oleg.
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2013-01-10 11:44 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-09 11:24 [RFC PATCH v2 0/4] uprobes: return probe implementation Anton Arapov
2013-01-09 11:24 ` [RFC PATCH v2 1/4] uretprobes/x86: hijack return address Anton Arapov
2013-01-09 11:24 ` [RFC PATCH v2 2/4] uretprobes: trampoline implementation Anton Arapov
2013-01-09 16:13 ` Oleg Nesterov
2013-01-09 11:24 ` [RFC PATCH v2 3/4] uretprobes: return probe entry, prepare uretprobe Anton Arapov
2013-01-09 16:17 ` Oleg Nesterov
2013-01-10 11:44 ` Anton Arapov
2013-01-09 11:24 ` [RFC PATCH v2 4/4] uretprobes: invoke return probe handlers Anton Arapov
2013-01-09 16:28 ` Oleg Nesterov
2013-01-10 11:42 ` Anton Arapov
2013-01-09 16:12 ` [RFC PATCH v2 0/4] uprobes: return probe implementation Oleg Nesterov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.