All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ptrace: add ability to get/set signal-blocked mask (v2)
@ 2013-04-23 15:10 Andrey Vagin
  2013-04-23 15:21 ` Oleg Nesterov
  0 siblings, 1 reply; 4+ messages in thread
From: Andrey Vagin @ 2013-04-23 15:10 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andrey Vagin, Roland McGrath, Oleg Nesterov, Andrew Morton,
	Michael Kerrisk, Pavel Emelyanov, Cyrill Gorcunov

crtools uses a parasite code for dumping processes. The parasite code is
injected into a process with help PTRACE_SEIZE.

Currently crtools blocks signals from a parasite code. If a process has
pending signals, crtools wait while a process handles these signals.

This method is not suitable for stopped tasks. A stopped task can have a
few pending signals, when we will try to execute a parasite code, we
will need to drop SIGSTOP, but all other signals must remain pending,
because a state of processes must not be changed during checkpointing.

This patch adds two ptrace commands to set/get signal-blocked mask.

I think gdb can use this commands too.

v2: Don't use __set_task_blocked with tsk != current.
recalc_sigpending() is not called here, because it will be called after
resume. retarget_shared_pending() are not called, because we suppose,
that other threads are stopped too.

Cc: Roland McGrath <roland@redhat.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
 include/uapi/linux/ptrace.h |  3 +++
 kernel/ptrace.c             | 42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index 52ebcc8..cf1019e 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -61,6 +61,9 @@ struct ptrace_peeksiginfo_args {
 	__s32 nr;	/* how may siginfos to take */
 };
 
+#define PTRACE_GETSIGMASK	0x420a
+#define PTRACE_SETSIGMASK	0x420b
+
 /* Read signals from a shared (process wide) queue */
 #define PTRACE_PEEKSIGINFO_SHARED	(1 << 0)
 
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 17ae54d..bebe67e 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -841,6 +841,48 @@ int ptrace_request(struct task_struct *child, long request,
 			ret = ptrace_setsiginfo(child, &siginfo);
 		break;
 
+	case PTRACE_GETSIGMASK:
+		if (addr != sizeof(sigset_t)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t)))
+			ret = -EFAULT;
+		else
+			ret = 0;
+
+		break;
+
+	case PTRACE_SETSIGMASK:
+	{
+		sigset_t new_set;
+
+		if (addr != sizeof(sigset_t)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user(&new_set, datavp, sizeof(sigset_t))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+		/*
+		 * Every thread does recalc_sigpending() after resume, so
+		 * retarget_shared_pending() and recalc_sigpending() are not
+		 * called here.
+		 */
+		spin_lock_irq(&child->sighand->siglock);
+		child->blocked = new_set;
+		spin_unlock_irq(&child->sighand->siglock);
+
+		ret = 0;
+		break;
+	}
+
 	case PTRACE_INTERRUPT:
 		/*
 		 * Stop tracee without any side-effect on signal or job
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] ptrace: add ability to get/set signal-blocked mask (v2)
  2013-04-23 15:10 [PATCH] ptrace: add ability to get/set signal-blocked mask (v2) Andrey Vagin
@ 2013-04-23 15:21 ` Oleg Nesterov
  2013-05-06  8:03   ` Andrew Vagin
  0 siblings, 1 reply; 4+ messages in thread
From: Oleg Nesterov @ 2013-04-23 15:21 UTC (permalink / raw)
  To: Andrey Vagin
  Cc: linux-kernel, Roland McGrath, Andrew Morton, Michael Kerrisk,
	Pavel Emelyanov, Cyrill Gorcunov

On 04/23, Andrey Vagin wrote:
>
> @@ -841,6 +841,48 @@ int ptrace_request(struct task_struct *child, long request,
>  			ret = ptrace_setsiginfo(child, &siginfo);
>  		break;
>  
> +	case PTRACE_GETSIGMASK:
> +		if (addr != sizeof(sigset_t)) {
> +			ret = -EINVAL;
> +			break;
> +		}
> +
> +		if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t)))
> +			ret = -EFAULT;

Yes, we can do this lockless. Only the task itself (or the debugger with
this patch) can change ->blocked, and the tracee can't run.

> +	case PTRACE_SETSIGMASK:
> +	{
> +		sigset_t new_set;
> +
> +		if (addr != sizeof(sigset_t)) {
> +			ret = -EINVAL;
> +			break;
> +		}
> +
> +		if (copy_from_user(&new_set, datavp, sizeof(sigset_t))) {
> +			ret = -EFAULT;
> +			break;
> +		}
> +
> +		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
> +
> +		/*
> +		 * Every thread does recalc_sigpending() after resume, so
> +		 * retarget_shared_pending() and recalc_sigpending() are not
> +		 * called here.
> +		 */
> +		spin_lock_irq(&child->sighand->siglock);
> +		child->blocked = new_set;
> +		spin_unlock_irq(&child->sighand->siglock);
> +
> +		ret = 0;
> +		break;
> +	}

And this looks fine too.

Personally I am not sure we need to check addr == sizeof(), debugger
should know what it does... But I won't argue.

Oleg.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ptrace: add ability to get/set signal-blocked mask (v2)
  2013-04-23 15:21 ` Oleg Nesterov
@ 2013-05-06  8:03   ` Andrew Vagin
  0 siblings, 0 replies; 4+ messages in thread
From: Andrew Vagin @ 2013-05-06  8:03 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andrey Vagin, linux-kernel, Roland McGrath, Michael Kerrisk,
	Pavel Emelyanov, Cyrill Gorcunov, Oleg Nesterov

Andrew, let me know if you are waiting something to accept this patch.

Thanks.

On Tue, Apr 23, 2013 at 05:21:43PM +0200, Oleg Nesterov wrote:
> On 04/23, Andrey Vagin wrote:
> >
> > @@ -841,6 +841,48 @@ int ptrace_request(struct task_struct *child, long request,
> >  			ret = ptrace_setsiginfo(child, &siginfo);
> >  		break;
> >  
> > +	case PTRACE_GETSIGMASK:
> > +		if (addr != sizeof(sigset_t)) {
> > +			ret = -EINVAL;
> > +			break;
> > +		}
> > +
> > +		if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t)))
> > +			ret = -EFAULT;
> 
> Yes, we can do this lockless. Only the task itself (or the debugger with
> this patch) can change ->blocked, and the tracee can't run.
> 
> > +	case PTRACE_SETSIGMASK:
> > +	{
> > +		sigset_t new_set;
> > +
> > +		if (addr != sizeof(sigset_t)) {
> > +			ret = -EINVAL;
> > +			break;
> > +		}
> > +
> > +		if (copy_from_user(&new_set, datavp, sizeof(sigset_t))) {
> > +			ret = -EFAULT;
> > +			break;
> > +		}
> > +
> > +		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
> > +
> > +		/*
> > +		 * Every thread does recalc_sigpending() after resume, so
> > +		 * retarget_shared_pending() and recalc_sigpending() are not
> > +		 * called here.
> > +		 */
> > +		spin_lock_irq(&child->sighand->siglock);
> > +		child->blocked = new_set;
> > +		spin_unlock_irq(&child->sighand->siglock);
> > +
> > +		ret = 0;
> > +		break;
> > +	}
> 
> And this looks fine too.
> 
> Personally I am not sure we need to check addr == sizeof(), debugger
> should know what it does... But I won't argue.

We do the same thing in sys_rt_sigaction. I think it may be useful in a
future, if we decide to change the size of sigset_t.

> 
> Oleg.
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] ptrace: add ability to get/set signal-blocked mask (v2)
@ 2013-05-22 16:51 Andrey Vagin
  0 siblings, 0 replies; 4+ messages in thread
From: Andrey Vagin @ 2013-05-22 16:51 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-kernel, Andrey Vagin, Roland McGrath, Michael Kerrisk,
	Pavel Emelyanov, Cyrill Gorcunov

crtools uses a parasite code for dumping processes. The parasite code is
injected into a process with help PTRACE_SEIZE.

Currently crtools blocks signals from a parasite code. If a process has
pending signals, crtools wait while a process handles these signals.

This method is not suitable for stopped tasks. A stopped task can have a
few pending signals, when we will try to execute a parasite code, we
will need to drop SIGSTOP, but all other signals must remain pending,
because a state of processes must not be changed during checkpointing.

This patch adds two ptrace commands to set/get signal-blocked mask.

I think gdb can use this commands too.

v2: Don't use __set_task_blocked with tsk != current.
recalc_sigpending() is not called here, because it will be called after
resume. retarget_shared_pending() are not called, because we suppose,
that other threads are stopped too.

Cc: Roland McGrath <roland@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
 include/uapi/linux/ptrace.h |  3 +++
 kernel/ptrace.c             | 42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index 52ebcc8..cf1019e 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -61,6 +61,9 @@ struct ptrace_peeksiginfo_args {
 	__s32 nr;	/* how may siginfos to take */
 };
 
+#define PTRACE_GETSIGMASK	0x420a
+#define PTRACE_SETSIGMASK	0x420b
+
 /* Read signals from a shared (process wide) queue */
 #define PTRACE_PEEKSIGINFO_SHARED	(1 << 0)
 
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index aed981a..f7f6112 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -842,6 +842,48 @@ int ptrace_request(struct task_struct *child, long request,
 			ret = ptrace_setsiginfo(child, &siginfo);
 		break;
 
+	case PTRACE_GETSIGMASK:
+		if (addr != sizeof(sigset_t)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t)))
+			ret = -EFAULT;
+		else
+			ret = 0;
+
+		break;
+
+	case PTRACE_SETSIGMASK:
+	{
+		sigset_t new_set;
+
+		if (addr != sizeof(sigset_t)) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user(&new_set, datavp, sizeof(sigset_t))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+		/*
+		 * Every thread does recalc_sigpending() after resume, so
+		 * retarget_shared_pending() and recalc_sigpending() are not
+		 * called here.
+		 */
+		spin_lock_irq(&child->sighand->siglock);
+		child->blocked = new_set;
+		spin_unlock_irq(&child->sighand->siglock);
+
+		ret = 0;
+		break;
+	}
+
 	case PTRACE_INTERRUPT:
 		/*
 		 * Stop tracee without any side-effect on signal or job
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-05-22 16:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-23 15:10 [PATCH] ptrace: add ability to get/set signal-blocked mask (v2) Andrey Vagin
2013-04-23 15:21 ` Oleg Nesterov
2013-05-06  8:03   ` Andrew Vagin
2013-05-22 16:51 Andrey Vagin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.