| <http://linux.llnl.gov/software/kernel/ptrace.html> |
| |
| The Linux kernels must implement ptrace semantics required by the TotalView |
| debugger. In order to initiate a parallel job under debugger control, a |
| resource manager or job launch utility must be able to start all tasks |
| in a stopped state, notify TotalView, and then allow TotalView debugger |
| servers to attach to all tasks. This functionality requires the ability to: |
| |
| * Detach from a traced process and leave the process stopped |
| * Attach to a stopped process |
| |
| Most newer versions of the Linux kernel support this functionality. For |
| some older Linux kernels, both of the above are impossible without the |
| following patch by Vic Zandy: |
| |
| * initial posting <http://seclists.org/linux-kernel/2001/Dec/5146.html> |
| * follow up <http://seclists.org/lists/linux-kernel/2002/Mar/4490.html> |
| |
| Further discussion of Vic's patch can be found in this thread |
| <http://seclists.org/lists/linux-kernel/2003/Mar/4457.html>. The main |
| objections to the patch seemed to be |
| |
| * It causes a behavior change for ptrace() |
| * No apparent agreement on the "right" thing to do when attaching to |
| a stopped process. |
| |
| [Any Etnus or Quadrics references to patches available?] |
| |
| On a vanilla 2.6.4 kernel, the ptrace() test is able to accomplish part |
| 1 of the test (detaching from a process and leaving the process |
| stopped), but part 2 (attaching to a stopped process) appears to still |
| be failing. |
| |
| It is possible to workaround a failure of step 2. Technically, it is not |
| the attach that hangs when doing a ptrace() of a stopped process, but |
| the subsequent call to waitpid(). Since the process was already stopped, |
| the waitpid() never returns. Perhaps Etnus has implemented a workaround |
| for this behavior. |
| |
| Testing: |
| |
| The followinbg piece of test code can be used to verify that the proper |
| functionality exists in the current kernel: |
| |
| testptrace.c <http://linux.llnl.gov/software/kernel/testptrace.c> |
| |
| This test should succeed when run without any arguments. |
| |
| ------------------------------------------------------------------------ |
| |
| <http://www.seclists.org/lists/linux-kernel/202/Mar/4490.html> |
| |
| Linux Kernel: Re: [PATCH] ptrace on stopped processes (2.4) |
| From: Vic Zandy@cs.wisc.edu |
| Date: Mar 18 2002 |
| |
| |
| This is a repost of the ptrace patch to 2.4 kernels |
| we've discussed in recent months. |
| |
| Since the last post, I have updated it to linux 2.4.18 |
| (no changes) and tested it with subterfuge and uml. |
| |
| Subterfuge seems to be unaffected. |
| |
| UML needs minor modifications; I've discussed them with |
| Jeff Dike and (I believe) he is happy. |
| |
| I believe I have addressed everyone's concerns. |
| |
| The patch fixes these two bugs: |
| |
| 1. gdb and other tools cannot attach to a stopped |
| process. The wait that follows the PTRACE_ATTACH |
| will block indefinitely. |
| |
| 2. It is not possible to use PTRACE_DETACH to leave |
| a process stopped, because ptrace ignores SIGSTOPs |
| sent by the tracing process. |
| |
| Vic |
| |
| --- /home/vic/p/linux-2.4.18.orig/kernel/ptrace.c Wed Mar 13 13:14:54 2002 |
| +++ /home/vic/p/linux-2.4.18/kernel/ptrace.c Mon Mar 18 21:58:11 2002 |
| @@ -54,6 +54,7 @@ |
| |
| int ptrace_attach(struct task_struct *task) |
| { |
| + int stopped; |
| task_lock(task); |
| if (task->pid <= 1) |
| goto bad; |
| @@ -90,7 +91,13 @@ |
| } |
| write_unlock_irq(&tasklist_lock); |
| |
| + stopped = (task->state == TASK_STOPPED); |
| send_sig(SIGSTOP, task, 1); |
| + /* If it was stopped when we got here, |
| + clear the pending SIGSTOP. */ |
| + if (stopped) |
| + wake_up_process(task); |
| + |
| return 0; |
| |
| bad: |
| --- /home/vic/p/linux-2.4.18.orig/arch/i386/kernel/signal.c Wed Mar 13 |
| 13:16:44 2002 |
| +++ /home/vic/p/linux-2.4.18/arch/i386/kernel/signal.c Wed Mar 13 |
| 16:31:38 2002 |
| @@ -620,9 +620,9 @@ |
| continue; |
| current->exit_code = 0; |
| |
| - /* The debugger continued. Ignore SIGSTOP. */ |
| - if (signr == SIGSTOP) |
| - continue; |
| + /* The debugger continued. */ |
| + if (signr == SIGSTOP && current->ptrace & PT_PTRACED) |
| + continue; /* ignore SIGSTOP */ |
| |
| /* Update the siginfo structure. Is this good? */ |
| if (signr != info.si_signo) { |
| - |
| |
| ------------------------------------------------------------------------ |