linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: oleg@redhat.com, jan.kratochvil@redhat.com, vda.linux@googlemail.com
Cc: linux-kernel@vger.kernel.org, torvalds@linux-foundation.org,
	akpm@linux-foundation.org, indan@nul.nu,
	Tejun Heo <tj@kernel.org>
Subject: [PATCH 04/11] ptrace: implement PTRACE_INTERRUPT
Date: Sun,  8 May 2011 17:48:58 +0200	[thread overview]
Message-ID: <1304869745-1073-5-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1304869745-1073-1-git-send-email-tj@kernel.org>

Currently, there's no way to trap a running ptracee short of sending a
signal which has various side effects.  This patch implements
PTRACE_INTERRUPT which traps ptracee without any signal or job control
related side effect.

The implementation is almost trivial.  It uses the same trap site and
event as PTRACE_SEIZE.  A new trap flag JOBCTL_TRAP_INTERRUPT is
added, which is set on PTRACE_INTERRUPT and cleared when tracee
commits to INTERRUPT trap.  As INTERRUPT should be useable regardless
of the current state of tracee, task_is_traced() test in
ptrace_check_attach() is skipped for INTERRUPT.

PTRACE_INTERRUPT is available iff tracee is attached with
PTRACE_SEIZE.

Test program follows.

  #define PTRACE_SEIZE		0x4206
  #define PTRACE_INTERRUPT	0x4207

  #define PTRACE_SEIZE_DEVEL	0x80000000

  static const struct timespec ts100ms = { .tv_nsec = 100000000 };
  static const struct timespec ts1s = { .tv_sec = 1 };
  static const struct timespec ts3s = { .tv_sec = 3 };

  int main(int argc, char **argv)
  {
	  pid_t tracee;

	  tracee = fork();
	  if (tracee == 0) {
		  nanosleep(&ts100ms, NULL);
		  while (1) {
			  printf("tracee: alive pid=%d\n", getpid());
			  nanosleep(&ts1s, NULL);
		  }
	  }

	  if (argc > 1)
		  kill(tracee, SIGSTOP);

	  nanosleep(&ts100ms, NULL);

	  ptrace(PTRACE_SEIZE, tracee, NULL,
		 (void *)(unsigned long)PTRACE_SEIZE_DEVEL);
	  waitid(P_PID, tracee, NULL, WSTOPPED);
	  ptrace(PTRACE_CONT, tracee, NULL, NULL);
	  nanosleep(&ts3s, NULL);

	  printf("tracer: INTERRUPT and DETACH\n");
	  ptrace(PTRACE_INTERRUPT, tracee, NULL, NULL);
	  waitid(P_PID, tracee, NULL, WSTOPPED);
	  ptrace(PTRACE_DETACH, tracee, NULL, NULL);
	  nanosleep(&ts3s, NULL);

	  printf("tracer: exiting\n");
	  kill(tracee, SIGKILL);
	  return 0;
  }

When called without argument, tracee is seized from running state,
continued, interrupted and then detached back to running state.

  # ./test-interrupt
  tracee: alive pid=4546
  tracee: alive pid=4546
  tracee: alive pid=4546
  tracer: INTERRUPT and DETACH
  tracee: alive pid=4546
  tracee: alive pid=4546
  tracee: alive pid=4546
  tracer: exiting

When called with argument, it's the same but tracee is detached back
to stopped state.

  # ./test-interrupt  1
  tracee: alive pid=4548
  tracee: alive pid=4548
  tracee: alive pid=4548
  tracer: INTERRUPT and DETACH
  tracer: exiting

Before PTRACE_INTERRUPT, once the tracee was continued, there was no
easy way to do PTRACE_DETACH without causing side effect as tracee
couldn't be trapped without side effect.

Signed-off-by: Tejun Heo <tj@kernel.org>
---
 include/linux/ptrace.h |    1 +
 include/linux/sched.h  |    3 ++-
 kernel/ptrace.c        |   23 +++++++++++++++++++++--
 kernel/signal.c        |    4 ++++
 4 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 8de301a..5b6128b 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -48,6 +48,7 @@
 #define PTRACE_SETREGSET	0x4205
 
 #define PTRACE_SEIZE		0x4206
+#define PTRACE_INTERRUPT	0x4207
 
 /* flags in @data for PTRACE_SEIZE */
 #define PTRACE_SEIZE_DEVEL	0x80000000 /* temp flag for development */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2f383eb..221ab51 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1785,9 +1785,10 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
 #define JOBCTL_STOP_PENDING	(1 << 17) /* task should stop for group stop */
 #define JOBCTL_STOP_CONSUME	(1 << 18) /* consume group stop count */
 #define JOBCTL_TRAP_SEIZE	(1 << 19) /* trap for seize */
+#define JOBCTL_TRAP_INTERRUPT	(1 << 20) /* trap for interrupt */
 #define JOBCTL_TRAPPING		(1 << 22) /* switching to TRACED */
 
-#define JOBCTL_TRAP_MASK	JOBCTL_TRAP_SEIZE
+#define JOBCTL_TRAP_MASK	(JOBCTL_TRAP_SEIZE | JOBCTL_TRAP_INTERRUPT)
 #define JOBCTL_PENDING_MASK	(JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK)
 
 extern void task_clear_jobctl_stop_pending(struct task_struct *task);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 0f0121a..1262a36 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -693,6 +693,23 @@ int ptrace_request(struct task_struct *child, long request,
 			ret = ptrace_setsiginfo(child, &siginfo);
 		break;
 
+	case PTRACE_INTERRUPT:
+		if (!likely(child->ptrace & PT_SEIZED))
+			break;
+		/*
+		 * Stop tracee without any side-effect on signal or job
+		 * control.  If @child is already trapped, the current trap
+		 * is not disturbed and INTERRUPT trap will happen after
+		 * the current trap is ended with PTRACE_CONT.  Note that
+		 * other traps may happen before the scheduled INTERRUPT.
+		 */
+		spin_lock(&child->sighand->siglock);
+		child->jobctl |= JOBCTL_TRAP_INTERRUPT;
+		signal_wake_up(child, 0);
+		spin_unlock(&child->sighand->siglock);
+		ret = 0;
+		break;
+
 	case PTRACE_DETACH:	 /* detach a process that was attached. */
 		ret = ptrace_detach(child, data);
 		break;
@@ -818,7 +835,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
 		goto out_put_task_struct;
 	}
 
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
+				  request == PTRACE_INTERRUPT);
 	if (ret < 0)
 		goto out_put_task_struct;
 
@@ -960,7 +978,8 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
 		goto out_put_task_struct;
 	}
 
-	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
+				  request == PTRACE_INTERRUPT);
 	if (!ret)
 		ret = compat_arch_ptrace(child, request, addr, data);
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 9249230..7add912 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1711,6 +1711,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 	__releases(&current->sighand->siglock)
 	__acquires(&current->sighand->siglock)
 {
+	bool is_intr = exit_code == (SIGTRAP | (PTRACE_EVENT_INTERRUPT << 8));
 	bool gstop_done = false;
 
 	if (arch_ptrace_stop_needed(exit_code, info)) {
@@ -1760,6 +1761,9 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 	task_clear_jobctl_trapping(current);
 	current->jobctl &= ~JOBCTL_TRAP_SEIZE;
 
+	if (is_intr)
+		current->jobctl &= ~JOBCTL_TRAP_INTERRUPT;
+
 	spin_unlock_irq(&current->sighand->siglock);
 	read_lock(&tasklist_lock);
 	if (may_ptrace_stop()) {
-- 
1.7.1


  parent reply	other threads:[~2011-05-08 15:49 UTC|newest]

Thread overview: 115+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-08 15:48 [PATCHSET ptrace] ptrace: implement PTRACE_SEIZE/INTERRUPT and group stop notification Tejun Heo
2011-05-08 15:48 ` [PATCH 01/11] job control: rename signal->group_stop and flags to jobctl and rearrange flags Tejun Heo
2011-05-08 15:48 ` [PATCH 02/11] ptrace: implement PTRACE_SEIZE Tejun Heo
2011-05-09 16:18   ` Oleg Nesterov
2011-05-10  9:46     ` Tejun Heo
2011-05-10 13:20       ` Oleg Nesterov
2011-05-10 13:47         ` Tejun Heo
2011-05-10 18:19           ` Oleg Nesterov
2011-05-15 15:56   ` PTRACE_SEIZE should not stop [Re: [PATCH 02/11] ptrace: implement PTRACE_SEIZE] Jan Kratochvil
2011-05-15 16:26     ` Tejun Heo
2011-05-15 17:15       ` Jan Kratochvil
2011-05-15 17:25         ` Tejun Heo
2011-05-15 19:48           ` Jan Kratochvil
2011-05-16  8:31             ` Tejun Heo
2011-05-16 12:26               ` Jan Kratochvil
2011-05-16 12:42                 ` Tejun Heo
2011-05-16 13:03                   ` Jan Kratochvil
2011-05-16 13:51                     ` Tejun Heo
2011-05-16 13:21               ` Jan Kratochvil
2011-05-16 13:45                 ` Tejun Heo
2011-05-16 13:48                   ` Jan Kratochvil
2011-05-16 13:54                     ` Tejun Heo
2011-05-08 15:48 ` [PATCH 03/11] ptrace: ptrace_check_attach(): rename @kill to @ignore_state and add comments Tejun Heo
2011-05-08 15:48 ` Tejun Heo [this message]
2011-05-08 21:58   ` [PATCH 04/11] ptrace: implement PTRACE_INTERRUPT Denys Vlasenko
2011-05-09 10:09     ` Tejun Heo
2011-05-09 10:55       ` Denys Vlasenko
2011-05-09 16:58   ` Oleg Nesterov
2011-05-10  9:50     ` Tejun Heo
2011-05-10 14:06       ` Oleg Nesterov
2011-05-10 14:20         ` Tejun Heo
2011-05-10 18:08           ` Oleg Nesterov
2011-05-11  8:29             ` Tejun Heo
2011-05-12 17:06               ` Oleg Nesterov
2011-05-12 17:21                 ` Tejun Heo
2011-05-10 21:59         ` Denys Vlasenko
2011-05-11  9:19           ` Tejun Heo
2011-05-11 12:23             ` Denys Vlasenko
2011-05-11 13:22               ` Tejun Heo
2011-05-11 16:20                 ` Bryan Donlan
2011-05-11 19:24                   ` Tejun Heo
2011-05-15 16:10             ` PTRACE_DETACH without stop [Re: [PATCH 04/11] ptrace: implement PTRACE_INTERRUPT] Jan Kratochvil
2011-05-15 16:35               ` Tejun Heo
2011-05-15 17:39                 ` Jan Kratochvil
2011-05-16  9:01                   ` Tejun Heo
2011-05-16 12:08                     ` Jan Kratochvil
2011-05-16 12:24                       ` Tejun Heo
2011-05-08 15:48 ` [PATCH 05/11] ptrace: restructure ptrace_getsiginfo() Tejun Heo
2011-05-08 15:49 ` [PATCH 06/11] ptrace: make group stop state visible via PTRACE_GETSIGINFO Tejun Heo
2011-05-10 16:55   ` Oleg Nesterov
2011-05-10 17:11     ` Oleg Nesterov
2011-05-11  8:08     ` Tejun Heo
2011-05-12 16:47       ` Oleg Nesterov
2011-05-12 17:15         ` Tejun Heo
2011-05-08 15:49 ` [PATCH 07/11] ptrace: add JOBCTL_TRAPPED Tejun Heo
2011-05-08 15:49 ` [PATCH 08/11] ptrace: move fallback JOBCTL_TRAPPING clearing to get_signal_to_deliver() Tejun Heo
2011-05-11 15:48   ` Oleg Nesterov
2011-05-11 19:17     ` Tejun Heo
2011-05-12 15:40       ` Oleg Nesterov
2011-05-08 15:49 ` [PATCH 09/11] job control: reorganize wait_task_stopped() Tejun Heo
2011-05-11 15:48   ` Oleg Nesterov
2011-05-11 19:29     ` Tejun Heo
2011-05-12 15:42       ` Oleg Nesterov
2011-05-12 16:02         ` Tejun Heo
2011-05-12 17:25           ` Oleg Nesterov
2011-05-12 17:32             ` Tejun Heo
2011-05-12 17:33               ` Tejun Heo
2011-05-12 18:33               ` Oleg Nesterov
2011-05-13  8:46                 ` Tejun Heo
2011-05-13 17:21                   ` Oleg Nesterov
2011-05-14 10:56                     ` Tejun Heo
2011-05-15 14:40               ` waitpid(WNOHANG) should report SIGCHLD-notified signals [Re: [PATCH 09/11] job control: reorganize wait_task_stopped()] Jan Kratochvil
2011-05-15 16:47                 ` Tejun Heo
2011-05-15 17:01                   ` Tejun Heo
2011-05-15 17:47                   ` Jan Kratochvil
2011-05-16  9:13                     ` Tejun Heo
2011-05-16 12:11                       ` Jan Kratochvil
2011-05-16 12:27                         ` Tejun Heo
2011-05-16 12:39                           ` Jan Kratochvil
2011-05-16 12:46                             ` Tejun Heo
2011-05-08 15:49 ` [PATCH 10/11] ptrace: move JOBCTL_TRAPPING wait to wait(2) and ptrace_check_attach() Tejun Heo
2011-05-11 16:49   ` Oleg Nesterov
2011-05-11 17:00     ` Oleg Nesterov
2011-05-11 19:45       ` Tejun Heo
2011-05-11 19:53     ` Tejun Heo
2011-05-12 10:23       ` Tejun Heo
2011-05-12 16:06         ` Oleg Nesterov
2011-05-12 15:59       ` Oleg Nesterov
2011-05-12 16:07         ` Tejun Heo
2011-05-12 18:20           ` Oleg Nesterov
2011-05-13  9:13             ` Tejun Heo
2011-05-13 18:34               ` Oleg Nesterov
2011-05-08 15:49 ` [PATCH 11/11] ptrace: implement group stop notification for ptracer Tejun Heo
2011-05-08 22:42   ` Denys Vlasenko
2011-05-09 10:10     ` Tejun Heo
2011-05-10 22:37   ` Denys Vlasenko
2011-05-11  9:05     ` Tejun Heo
2011-05-11 12:01       ` Denys Vlasenko
2011-05-11 13:13         ` Tejun Heo
2011-05-11 19:58   ` Oleg Nesterov
2011-05-11 20:18     ` Tejun Heo
2011-05-11 20:21       ` Tejun Heo
2011-05-12 10:24         ` Tejun Heo
2011-05-15 14:02   ` getter PTRACE_GETSIGINFO should not modify anything [Re: [PATCH 11/11] ptrace: implement group stop notification for ptracer] Jan Kratochvil
2011-05-15 14:28     ` Tejun Heo
2011-05-15 17:17       ` Jan Kratochvil
2011-05-15 17:28         ` Tejun Heo
2011-05-15 20:06           ` Jan Kratochvil
2011-05-16  8:43             ` Tejun Heo
2011-05-16 12:17               ` Jan Kratochvil
2011-05-16 12:56                 ` Tejun Heo
2011-05-16 13:00                   ` Ingo Molnar
2011-05-08 22:27 ` [PATCHSET ptrace] ptrace: implement PTRACE_SEIZE/INTERRUPT and group stop notification Denys Vlasenko
2011-05-09  9:48   ` Tejun Heo
2011-05-15 13:55   ` ptrace-testsuite status [Re: [PATCHSET ptrace] ptrace: implement PTRACE_SEIZE/INTERRUPT and group stop notification] Jan Kratochvil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1304869745-1073-5-git-send-email-tj@kernel.org \
    --to=tj@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=indan@nul.nu \
    --cc=jan.kratochvil@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleg@redhat.com \
    --cc=torvalds@linux-foundation.org \
    --cc=vda.linux@googlemail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).