[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(&current->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