ptrace: Always put ptracee into appropriate execution state
authorTejun Heo <tj@kernel.org>
Wed, 23 Mar 2011 09:37:01 +0000 (10:37 +0100)
committerTejun Heo <tj@kernel.org>
Wed, 23 Mar 2011 09:37:01 +0000 (10:37 +0100)
commit0e9f0a4abfd80f8adca624538d479d95159b16d8
tree6b9910140f4755cd95970a5c559e8f00d60dfede
parente3bd058f62896ec7a2c605ed62a0a811e9147947
ptrace: Always put ptracee into appropriate execution state

Currently, __ptrace_unlink() wakes up the tracee iff it's in
TASK_TRACED.  For unlinking from PTRACE_DETACH, this is correct as the
tracee is guaranteed to be in TASK_TRACED or dead; however, unlinking
also happens when the ptracer exits and in this case the ptracee can
be in any state and ptrace might be left running even if the group it
belongs to is stopped.

This patch updates __ptrace_unlink() such that GROUP_STOP_PENDING is
reinstated regardless of the ptracee's current state as long as it's
alive and makes sure that signal_wake_up() is called if execution
state transition is necessary.

Test case follows.

  #include <unistd.h>
  #include <time.h>
  #include <sys/types.h>
  #include <sys/ptrace.h>
  #include <sys/wait.h>

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

  int main(void)
  {
  pid_t tracee;
  siginfo_t si;

  tracee = fork();
  if (tracee == 0) {
  while (1) {
  nanosleep(&ts1s, NULL);
  write(1, ".", 1);
  }
  }

  ptrace(PTRACE_ATTACH, tracee, NULL, NULL);
  waitid(P_PID, tracee, &si, WSTOPPED);
  ptrace(PTRACE_CONT, tracee, NULL, (void *)(long)si.si_status);
  waitid(P_PID, tracee, &si, WSTOPPED);
  ptrace(PTRACE_CONT, tracee, NULL, (void *)(long)si.si_status);
  write(1, "exiting", 7);
  return 0;
  }

Before the patch, after the parent process exits, the child is left
running and prints out "." every second.

  exiting..... (continues)

After the patch, the group stop initiated by the implied SIGSTOP from
PTRACE_ATTACH is re-established when the parent exits.

  exiting

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Oleg Nesterov <oleg@redhat.com>
kernel/ptrace.c