[CRIU] [PATCH] [RFC] ptrace: peek and send siginfo
Andrey Vagin
avagin at openvz.org
Mon Nov 26 16:41:40 EST 2012
This functionality is required for checkpointing and restoring
pending signals.
This patch adds two ptrace commands:
* to get siginfo for any signal with a specified sequence number
* to add a siginfo to a process
Could you comment this approach?
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
include/linux/signal.h | 2 ++
include/uapi/linux/ptrace.h | 3 +++
kernel/ptrace.c | 16 ++++++++++++++++
kernel/signal.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 67 insertions(+)
diff --git a/include/linux/signal.h b/include/linux/signal.h
index e19a011..605f999 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -239,6 +239,8 @@ struct pt_regs;
extern int next_signal(struct sigpending *pending, sigset_t *mask);
extern int do_send_sig_info(int sig, struct siginfo *info,
struct task_struct *p, bool group);
+extern int do_peek_siginfo(int sig, siginfo_t *info,
+ struct task_struct *p, s16 nr);
extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig,
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index 1ef6c05..47ff821 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -52,6 +52,9 @@
#define PTRACE_INTERRUPT 0x4207
#define PTRACE_LISTEN 0x4208
+#define PTRACE_PEEK_SIGINFO 0x4209
+#define PTRACE_SEND_SIGINFO 0x420a
+
/* Wait extended result codes for the above trace options. */
#define PTRACE_EVENT_FORK 1
#define PTRACE_EVENT_VFORK 2
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 1f5e55d..22111b6 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -707,6 +707,22 @@ int ptrace_request(struct task_struct *child, long request,
ret = ptrace_setsiginfo(child, &siginfo);
break;
+#ifdef CONFIG_CHECKPOINT_RESTORE
+ case PTRACE_PEEK_SIGINFO:
+ ret = do_peek_siginfo(addr & 0xffff, &siginfo, child, addr >> 16);
+ if (!ret)
+ ret = copy_siginfo_to_user(datavp, &siginfo);
+ break;
+
+ case PTRACE_SEND_SIGINFO:
+ if (copy_from_user(&siginfo, datavp, sizeof siginfo))
+ ret = -EFAULT;
+ else
+ ret = do_send_sig_info(siginfo.si_signo,
+ &siginfo, child, addr ? 1 : 0);
+ break;
+#endif
+
case PTRACE_INTERRUPT:
/*
* Stop tracee without any side-effect on signal or job
diff --git a/kernel/signal.c b/kernel/signal.c
index 0af8868..172c269 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -535,6 +535,52 @@ unblock_all_signals(void)
spin_unlock_irqrestore(¤t->sighand->siglock, flags);
}
+/*
+ * Get siginfo with a sequence number nr.
+ *
+ * If nr is positive, a signal will be picked of a shared queue.
+ * If nr is negative, a signal will be picked of a local queue.
+ */
+int do_peek_siginfo(int sig, siginfo_t *info, struct task_struct *tsk, s16 nr)
+{
+ unsigned long flags;
+ struct sigqueue *q;
+ struct sigpending *p;
+ int i = 0, ret = -ESRCH;
+
+ if (nr == 0)
+ return -EINVAL;
+
+ if (!lock_task_sighand(tsk, &flags))
+ return ret;
+
+ if (nr > 0) {
+ p = &tsk->signal->shared_pending;
+ } else {
+ nr = -nr;
+ p = &tsk->pending;
+ }
+
+ list_for_each_entry(q, &p->list, list) {
+ if (q->info.si_signo == sig) {
+ i++;
+ if (i == nr)
+ break;
+ }
+ }
+
+ if (i != nr)
+ goto unlock;
+
+ copy_siginfo(info, &q->info);
+ ret = 0;
+
+unlock:
+ unlock_task_sighand(tsk, &flags);
+
+ return ret;
+}
+
static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
{
struct sigqueue *q, *first = NULL;
--
1.7.11.7
More information about the CRIU
mailing list