[CRIU] [PATCH] [RFC] ptrace: peek and send siginfo
Pavel Emelyanov
xemul at parallels.com
Tue Nov 27 09:02:10 EST 2012
On 11/27/2012 01:41 AM, Andrey Vagin wrote:
> 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
Why not use the kill() syscall for the latter?
> 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;
>
More information about the CRIU
mailing list