linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: oleg@redhat.com
Cc: vda.linux@googlemail.com, jan.kratochvil@redhat.com,
	linux-kernel@vger.kernel.org, torvalds@linux-foundation.org,
	akpm@linux-foundation.org, indan@nul.nu, bdonlan@gmail.com,
	pedro@codesourcery.com, Tejun Heo <tj@kernel.org>
Subject: [PATCH 14/17] ptrace: make group stop state visible via PTRACE_GETSIGINFO
Date: Mon, 30 May 2011 01:12:37 +0200	[thread overview]
Message-ID: <1306710760-16440-15-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1306710760-16440-1-git-send-email-tj@kernel.org>

If tracee is SEIZED, PTRACE_EVENT_STOP trap is used for group stop;
however, there currently is no way to find out which signal initiated
the group stop or if the group stop is still in effect.

This patch updates ptrace_do_notify() such that it reports group stop
information via si.si_signo and si.si_pt_flags - both are stored in
siginfo on trap.  Note that it's only available if tracee was seized.

This doesn't address notification and tracer has to repeatedly put the
tracee into trap and poll the flag.  Later patches will deal with
notification and trap transition.

Test program follows.

  #define PTRACE_SEIZE		0x4206
  #define PTRACE_INTERRUPT	0x4207

  #define PTRACE_SEIZE_DEVEL	0x80000000

  static const struct timespec ts1s = { .tv_sec = 1 };

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

	  tracee = fork();
	  if (!tracee)
		  while (1)
			  nanosleep(&ts1s, NULL);

	  tracer = fork();
	  if (!tracer) {
		  int last_stopped = 0, stopped;
		  siginfo_t si;

		  ptrace(PTRACE_SEIZE, tracee, NULL,
			 (void *)(unsigned long)PTRACE_SEIZE_DEVEL);
	  repeat:
		  ptrace(PTRACE_INTERRUPT, tracee, NULL, NULL);
		  waitid(P_PID, tracee, NULL, WSTOPPED);

		  ptrace(PTRACE_GETSIGINFO, tracee, NULL, &si);
		  if (si.si_code) {
			  stopped = !!si.si_status;
			  if (stopped != last_stopped)
				  printf("tracer: stopped=%d signo=%d\n",
					 stopped, si.si_signo);
			  last_stopped = stopped;
			  ptrace(PTRACE_CONT, tracee, NULL, NULL);
		  } else {
			  printf("tracer: SIG %d\n", si.si_signo);
			  ptrace(PTRACE_CONT, tracee, NULL,
				 (void *)(unsigned long)si.si_signo);
		  }
		  goto repeat;
	  }

	  for (i = 0; i < 3; i++) {
		  nanosleep(&ts1s, NULL);
		  printf("mother: SIGSTOP\n");
		  kill(tracee, SIGSTOP);
		  nanosleep(&ts1s, NULL);
		  printf("mother: SIGCONT\n");
		  kill(tracee, SIGCONT);
	  }
	  nanosleep(&ts1s, NULL);

	  kill(tracer, SIGKILL);
	  kill(tracee, SIGKILL);
	  return 0;
  }

Tracer delivers signal, resumes group stop, induces INTERRUPT traps
and reports group stop state change in busy loop.  Mother sends
SIGSTOP or CONT to tracee on each second.  Note that si_pt_flags and
flag testing are replaced with si_status testing.  si_status occupies
the same offset as si_pt_flags and PTRACE_SI_STOPPED is the only flag
defined, so I took a dirty short cut.

  # ./test-stopped
  mother: SIGSTOP
  tracer: SIG 19
  tracer: stopped=1 signo=19
  mother: SIGCONT
  tracer: stopped=0 signo=5
  tracer: SIG 18
  mother: SIGSTOP
  tracer: SIG 19
  tracer: stopped=1 signo=19
  mother: SIGCONT
  tracer: stopped=0 signo=5
  tracer: SIG 18
  mother: SIGSTOP
  tracer: SIG 19
  tracer: stopped=1 signo=19
  mother: SIGCONT
  tracer: SIG 18
  tracer: stopped=0 signo=5

-v2: Local variable sig defined inside if() block it's used in as
     suggested by Oleg.

-v3: siginfo is filled in on trap rather than on PTRACE_GETSIGINFO as
     suggested by Oleg.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
---
 include/linux/ptrace.h |    3 +++
 kernel/signal.c        |    8 ++++++++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index ad754d1..f16a63f 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -73,6 +73,9 @@
 #define PTRACE_EVENT_EXIT	6
 #define PTRACE_EVENT_STOP	7
 
+/* flags in siginfo.si_pt_flags from PTRACE_GETSIGINFO */
+#define PTRACE_SI_STOPPED	0x00000001 /* tracee is job control stopped */
+
 #include <asm/ptrace.h>
 
 #ifdef __KERNEL__
diff --git a/kernel/signal.c b/kernel/signal.c
index 3f131be..c6ebdfe 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1875,6 +1875,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 
 static void ptrace_do_notify(int exit_code, int why)
 {
+	struct signal_struct *sig = current->signal;
 	siginfo_t info;
 
 	BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
@@ -1885,6 +1886,13 @@ static void ptrace_do_notify(int exit_code, int why)
 	info.si_pid = task_pid_vnr(current);
 	info.si_uid = current_uid();
 
+	if ((current->ptrace & PT_SEIZED) &&
+	    (sig->group_stop_count || sig->flags & SIGNAL_STOP_STOPPED)) {
+		info.si_pt_flags |= PTRACE_SI_STOPPED;
+		info.si_signo = current->jobctl & JOBCTL_STOP_SIGMASK;
+		WARN_ON_ONCE(!info.si_signo);
+	}
+
 	/* Let the debugger run.  */
 	ptrace_stop(exit_code, why, 1, &info);
 }
-- 
1.7.5.2


  parent reply	other threads:[~2011-05-29 23:14 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-29 23:12 [PATCHSET ptrace] ptrace: implement PTRACE_SEIZE/INTERRUPT and group stop notification, take#4 Tejun Heo
2011-05-29 23:12 ` [PATCH 01/17] ptrace: remove silly wait_trap variable from ptrace_attach() Tejun Heo
2011-06-01 18:47   ` Oleg Nesterov
2011-06-02  5:03     ` Tejun Heo
2011-06-02 11:39   ` [PATCH UPDATED " Tejun Heo
2011-05-29 23:12 ` [PATCH 02/17] job control: rename signal->group_stop and flags to jobctl and update them Tejun Heo
2011-05-29 23:12 ` [PATCH 03/17] ptrace: ptrace_check_attach(): rename @kill to @ignore_state and add comments Tejun Heo
2011-05-29 23:12 ` [PATCH 04/17] ptrace: relocate set_current_state(TASK_TRACED) in ptrace_stop() Tejun Heo
2011-05-29 23:12 ` [PATCH 05/17] job control: introduce JOBCTL_PENDING_MASK and task_clear_jobctl_pending() Tejun Heo
2011-05-29 23:12 ` [PATCH 06/17] job control: make task_clear_jobctl_pending() clear TRAPPING automatically Tejun Heo
2011-05-29 23:12 ` [PATCH 07/17] job control: introduce task_set_jobctl_pending() Tejun Heo
2011-05-29 23:12 ` [PATCH 08/17] ptrace: use bit_waitqueue for TRAPPING instead of wait_chldexit Tejun Heo
2011-06-02 11:41   ` [PATCH UPDATED " Tejun Heo
2011-05-29 23:12 ` [PATCH 09/17] signal: remove three noop tracehooks Tejun Heo
2011-05-29 23:12 ` [PATCH 10/17] job control: introduce JOBCTL_TRAP_STOP and use it for group stop trap Tejun Heo
2011-05-29 23:12 ` [PATCH 11/17] ptrace: implement PTRACE_SEIZE Tejun Heo
2011-06-01 19:01   ` Oleg Nesterov
2011-06-01 19:55     ` Oleg Nesterov
2011-06-02  5:13     ` Tejun Heo
2011-06-02 11:43   ` [PATCH UPDATED " Tejun Heo
2011-05-29 23:12 ` [PATCH 12/17] ptrace: implement PTRACE_INTERRUPT Tejun Heo
2011-05-29 23:12 ` [PATCH 13/17] ptrace: add siginfo.si_pt_flags Tejun Heo
2011-05-29 23:12 ` Tejun Heo [this message]
2011-05-29 23:12 ` [PATCH 15/17] ptrace: don't let PTRACE_SETSIGINFO override __SI_TRAP siginfo Tejun Heo
2011-05-29 23:12 ` [PATCH 16/17] ptrace: implement TRAP_NOTIFY and use it for group stop events Tejun Heo
2011-05-29 23:12 ` [PATCH 17/17] ptrace: implement PTRACE_LISTEN Tejun Heo
2011-06-02 17:33   ` Oleg Nesterov
2011-06-13 14:10     ` Tejun Heo
2011-06-13 20:33       ` Oleg Nesterov
2011-06-14  6:45         ` Tejun Heo
2011-05-30 15:42 ` [PATCHSET ptrace] ptrace: implement PTRACE_SEIZE/INTERRUPT and group stop notification, take#4 Oleg Nesterov
2011-06-01  5:39   ` Tejun Heo
2011-06-02 12:31     ` Tejun Heo
2011-06-02 14:51       ` Denys Vlasenko
2011-06-03  1:24         ` Tejun Heo
2011-06-03 10:25           ` Pedro Alves
2011-06-16  8:38             ` Tejun Heo
2011-06-16  9:56               ` Pedro Alves
2011-06-17 19:08                 ` Oleg Nesterov
2011-06-03 11:57           ` Denys Vlasenko
2011-06-03 12:11             ` Pedro Alves
2011-06-03 14:12               ` Denys Vlasenko
2011-06-03 15:24                 ` Pedro Alves
2011-06-03 15:46             ` Oleg Nesterov
2011-06-02 18:27       ` Oleg Nesterov
2011-06-02 21:09         ` Denys Vlasenko
2011-06-03  1:34           ` Tejun Heo
2011-06-03 11:37             ` Denys Vlasenko
2011-06-03 11:58               ` Denys Vlasenko
2011-06-03 15:37             ` Oleg Nesterov

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=1306710760-16440-15-git-send-email-tj@kernel.org \
    --to=tj@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=bdonlan@gmail.com \
    --cc=indan@nul.nu \
    --cc=jan.kratochvil@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=oleg@redhat.com \
    --cc=pedro@codesourcery.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).