Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29000cae authored by Andrey Vagin's avatar Andrey Vagin Committed by Linus Torvalds
Browse files

ptrace: add ability to get/set signal-blocked mask



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.

[akpm@linux-foundation.org: be consistent with brace layout]
Signed-off-by: default avatarAndrey Vagin <avagin@openvz.org>
Reviewed-by: default avatarOleg Nesterov <oleg@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 37f07655
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,9 @@ struct ptrace_peeksiginfo_args {
	__s32 nr;	/* how may siginfos to take */
	__s32 nr;	/* how may siginfos to take */
};
};


#define PTRACE_GETSIGMASK	0x420a
#define PTRACE_SETSIGMASK	0x420b

/* Read signals from a shared (process wide) queue */
/* Read signals from a shared (process wide) queue */
#define PTRACE_PEEKSIGINFO_SHARED	(1 << 0)
#define PTRACE_PEEKSIGINFO_SHARED	(1 << 0)


+42 −2
Original line number Original line Diff line number Diff line
@@ -844,6 +844,47 @@ int ptrace_request(struct task_struct *child, long request,
			ret = ptrace_setsiginfo(child, &siginfo);
			ret = ptrace_setsiginfo(child, &siginfo);
		break;
		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:
	case PTRACE_INTERRUPT:
		/*
		/*
		 * Stop tracee without any side-effect on signal or job
		 * Stop tracee without any side-effect on signal or job
@@ -948,8 +989,7 @@ int ptrace_request(struct task_struct *child, long request,


#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
	case PTRACE_GETREGSET:
	case PTRACE_GETREGSET:
	case PTRACE_SETREGSET:
	case PTRACE_SETREGSET: {
	{
		struct iovec kiov;
		struct iovec kiov;
		struct iovec __user *uiov = datavp;
		struct iovec __user *uiov = datavp;