lkml.org 
[lkml]   [2013]   [Mar]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC PATCH v4 5/6] uretprobes: invoke return probe handlers
Date

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.

v4:
- check, whether utask is not NULL in handle_uretprobe()
? do we want a printk() for this case?
- get rid of area->rp_trampoline_vaddr
- minor handle_uretprobe() fixups
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 | 57 ++++++++++++++++++++++++++++++++++++++++--
2 files changed, 60 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 12acc10..e86b6ea 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1574,6 +1574,55 @@ 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 xol_area *area, struct pt_regs *regs)
+{
+ struct hlist_head *head;
+ struct hlist_node *tmp;
+ struct return_uprobe_i *ri;
+ struct uprobe_task *utask;
+ unsigned long orig_ret_vaddr;
+
+ /* TODO: uretprobe bypass logic */
+
+ utask = get_utask();
+ if (!utask) {
+ /* TODO:RFC task is not probed, do we want printk here? */
+ return;
+ }
+ 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);
+ }
+
+ orig_ret_vaddr = ri->orig_ret_vaddr;
+ put_uprobe(ri->uprobe);
+ hlist_del(&ri->hlist);
+ kfree(ri);
+
+ if (orig_ret_vaddr != area->vaddr)
+ return;
+ }
+
+ /* TODO: change the message */
+ printk(KERN_ERR "uprobe: no instance found! 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.
@@ -1581,6 +1630,7 @@ 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);

@@ -1589,8 +1639,11 @@ static void handle_swbp(struct pt_regs *regs)

if (!uprobe) {
if (is_swbp > 0) {
- /* No matching uprobe; signal SIGTRAP. */
- send_sig(SIGTRAP, current, 0);
+ area = get_xol_area();
+ if (area && bp_vaddr == area->vaddr)
+ handle_uretprobe(area, regs);
+ else
+ send_sig(SIGTRAP, current, 0);
} else {
/*
* Either we raced with uprobe_unregister() or we can't
--
1.8.1.2


\
 
 \ /
  Last update: 2013-03-04 16:21    [W:0.085 / U:1.292 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site