- 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@xxxxxxxxxxxxxxxxxx> --- 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, ¤t->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(¤t->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); } /* -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>