lkml.org 
[lkml]   [2011]   [Sep]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Date
Subject[PATCH v5 3.1.0-rc4-tip 26/26] uprobes: queue signals while thread is singlestepping.

- Queue signals delivered from the time we singlestep till
completion of postprocessing. The queueing is done on a
per-task basis.
- After singlestep completion, dequeue the signals.

Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
---
include/linux/uprobes.h | 3 ++-
kernel/signal.c | 22 +++++++++++++++++++++-
kernel/uprobes.c | 22 ++++++++++++++++------
3 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index a407d17..189cdce 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -24,7 +24,7 @@
*/

#include <linux/rbtree.h>
-
+#include <linux/signal.h> /* sigpending */
struct vm_area_struct;
#ifdef CONFIG_ARCH_SUPPORTS_UPROBES
#include <asm/uprobes.h>
@@ -90,6 +90,7 @@ struct uprobe_task {
struct uprobe_task_arch_info tskinfo;

struct uprobe *active_uprobe;
+ struct sigpending delayed;
};

/*
diff --git a/kernel/signal.c b/kernel/signal.c
index 291c970..48b8c7c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1034,6 +1034,11 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
return 0;

pending = group ? &t->signal->shared_pending : &t->pending;
+#ifdef CONFIG_UPROBES
+ if (!group && t->utask && t->utask->active_uprobe)
+ pending = &t->utask->delayed;
+#endif
+
/*
* Short-circuit ignored signals and support queuing
* exactly one non-rt signal, so that we can get more
@@ -1106,6 +1111,11 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
}
}

+#ifdef CONFIG_UPROBES
+ if (!group && t->utask && t->utask->active_uprobe)
+ return 0;
+#endif
+
out_set:
signalfd_notify(t, sig);
sigaddset(&pending->signal, sig);
@@ -1569,6 +1579,13 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)
}
q->info.si_overrun = 0;

+#ifdef CONFIG_UPROBES
+ if (!group && t->utask && t->utask->active_uprobe) {
+ pending = &t->utask->delayed;
+ list_add_tail(&q->list, &pending->list);
+ goto out;
+ }
+#endif
signalfd_notify(t, sig);
pending = group ? &t->signal->shared_pending : &t->pending;
list_add_tail(&q->list, &pending->list);
@@ -2199,7 +2216,10 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
spin_unlock_irq(&sighand->siglock);
goto relock;
}
-
+#ifdef CONFIG_UPROBES
+ if (current->utask && current->utask->active_uprobe)
+ break;
+#endif
signr = dequeue_signal(current, &current->blocked, info);

if (!signr)
diff --git a/kernel/uprobes.c b/kernel/uprobes.c
index ca1f622..d065fa7 100644
--- a/kernel/uprobes.c
+++ b/kernel/uprobes.c
@@ -1298,11 +1298,14 @@ void free_uprobe_utask(struct task_struct *tsk)
static struct uprobe_task *add_utask(void)
{
struct uprobe_task *utask;
+ struct sigpending *delayed;

utask = kzalloc(sizeof *utask, GFP_KERNEL);
if (unlikely(utask == NULL))
return ERR_PTR(-ENOMEM);

+ delayed = &utask->delayed;
+ INIT_LIST_HEAD(&delayed->list);
utask->active_uprobe = NULL;
current->utask = utask;
return utask;
@@ -1337,6 +1340,16 @@ static bool sstep_complete(struct uprobe *uprobe, struct pt_regs *regs)
return true;
}

+static void pushback_signals(struct sigpending *pending)
+{
+ struct sigqueue *q, *tmpq;
+
+ list_for_each_entry_safe(q, tmpq, &pending->list, list) {
+ list_del(&q->list);
+ send_sigqueue(q, current, 0);
+ }
+}
+
/*
* uprobe_notify_resume gets called in task context just before returning
* to userspace.
@@ -1373,7 +1386,6 @@ void uprobe_notify_resume(struct pt_regs *regs)
if (!utask)
goto cleanup_ret;
}
- /* TODO Start queueing signals. */
utask->active_uprobe = u;
handler_chain(u, regs);
utask->state = UTASK_SSTEP;
@@ -1390,8 +1402,7 @@ void uprobe_notify_resume(struct pt_regs *regs)
utask->state = UTASK_RUNNING;
user_disable_single_step(current);
xol_free_insn_slot(current);
-
- /* TODO Stop queueing signals. */
+ pushback_signals(&current->utask->delayed);
}
}
return;
@@ -1404,9 +1415,8 @@ void uprobe_notify_resume(struct pt_regs *regs)
if (u) {
put_uprobe(u);
set_instruction_pointer(regs, probept);
- } else {
- /*TODO Return SIGTRAP signal */
- }
+ } else
+ send_sig(SIGTRAP, current, 0);
}

/*

\
 
 \ /
  Last update: 2011-09-20 14:21    [W:0.702 / U:0.360 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site