]> err.no Git - linux-2.6/commitdiff
Fix spurious syscall tracing after PTRACE_DETACH + PTRACE_ATTACH
authorRoland McGrath <roland@redhat.com>
Wed, 5 Sep 2007 10:05:56 +0000 (03:05 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 11 Sep 2007 01:57:47 +0000 (18:57 -0700)
When PTRACE_SYSCALL was used and then PTRACE_DETACH is used, the
TIF_SYSCALL_TRACE flag is left set on the formerly-traced task.  This
means that when a new tracer comes along and does PTRACE_ATTACH, it's
possible he gets a syscall tracing stop even though he's never used
PTRACE_SYSCALL.  This happens if the task was in the middle of a system
call when the second PTRACE_ATTACH was done.  The symptom is an
unexpected SIGTRAP when the tracer thinks that only SIGSTOP should have
been provoked by his ptrace calls so far.

A few machines already fixed this in ptrace_disable (i386, ia64, m68k).
But all other machines do not, and still have this bug.  On x86_64, this
constitutes a regression in IA32 compatibility support.

Since all machines now use TIF_SYSCALL_TRACE for this, I put the
clearing of TIF_SYSCALL_TRACE in the generic ptrace_detach code rather
than adding it to every other machine's ptrace_disable.

Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/i386/kernel/ptrace.c
arch/ia64/kernel/ptrace.c
arch/m68k/kernel/ptrace.c
kernel/ptrace.c

index 0c8f00e69c4d92630256a6530b03e4b4cf4d6190..7c1b92522e95c1177bfb2fb70df497c9262a4856 100644 (file)
@@ -274,7 +274,6 @@ static void clear_singlestep(struct task_struct *child)
 void ptrace_disable(struct task_struct *child)
 { 
        clear_singlestep(child);
-       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
        clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
 }
 
index 122444a97897d7f02a7707cdd3f178248a1efdf5..2e96f17b2f3b9e2c0b905deddcc02df21c88517d 100644 (file)
@@ -1577,7 +1577,6 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
 
              case PTRACE_DETACH:
                /* detach a process that was attached. */
-               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                ret = ptrace_detach(child, data);
                goto out_tsk;
 
index 2cf0690b78824f2e4e668d8d982b6d483ee77621..e792d3cba4c73e8cdfc9ac0cfd2e163cd471fa93 100644 (file)
@@ -116,7 +116,6 @@ static inline void singlestep_disable(struct task_struct *child)
 void ptrace_disable(struct task_struct *child)
 {
        singlestep_disable(child);
-       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 }
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
index 82a558b655dabb9dc7990aedc804b9b04d8f1525..3eca7a55f2ee8b13fb2fb6f3e09ea2d7a685acaf 100644 (file)
@@ -233,6 +233,7 @@ int ptrace_detach(struct task_struct *child, unsigned int data)
 
        /* Architecture-specific hardware disable .. */
        ptrace_disable(child);
+       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 
        write_lock_irq(&tasklist_lock);
        /* protect against de_thread()->release_task() */