diff options
author | Roland McGrath <roland@redhat.com> | 2007-09-05 06:05:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-09-10 21:57:47 -0400 |
commit | 7d94143291e4e625e2bc3b1ebdc7143ee7a9a2f1 (patch) | |
tree | c4f8a974a33dd6ac1feacf18f217ee326c8af5eb | |
parent | 897ee77bfba12b83752027427a41009961458ee6 (diff) |
Fix spurious syscall tracing after PTRACE_DETACH + PTRACE_ATTACH
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>
-rw-r--r-- | arch/i386/kernel/ptrace.c | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/ptrace.c | 1 | ||||
-rw-r--r-- | arch/m68k/kernel/ptrace.c | 1 | ||||
-rw-r--r-- | kernel/ptrace.c | 1 |
4 files changed, 1 insertions, 3 deletions
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 0c8f00e69c4d..7c1b92522e95 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c | |||
@@ -274,7 +274,6 @@ static void clear_singlestep(struct task_struct *child) | |||
274 | void ptrace_disable(struct task_struct *child) | 274 | void ptrace_disable(struct task_struct *child) |
275 | { | 275 | { |
276 | clear_singlestep(child); | 276 | clear_singlestep(child); |
277 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
278 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | 277 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); |
279 | } | 278 | } |
280 | 279 | ||
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 122444a97897..2e96f17b2f3b 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c | |||
@@ -1577,7 +1577,6 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) | |||
1577 | 1577 | ||
1578 | case PTRACE_DETACH: | 1578 | case PTRACE_DETACH: |
1579 | /* detach a process that was attached. */ | 1579 | /* detach a process that was attached. */ |
1580 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
1581 | ret = ptrace_detach(child, data); | 1580 | ret = ptrace_detach(child, data); |
1582 | goto out_tsk; | 1581 | goto out_tsk; |
1583 | 1582 | ||
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 2cf0690b7882..e792d3cba4c7 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
@@ -116,7 +116,6 @@ static inline void singlestep_disable(struct task_struct *child) | |||
116 | void ptrace_disable(struct task_struct *child) | 116 | void ptrace_disable(struct task_struct *child) |
117 | { | 117 | { |
118 | singlestep_disable(child); | 118 | singlestep_disable(child); |
119 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
120 | } | 119 | } |
121 | 120 | ||
122 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 121 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 82a558b655da..3eca7a55f2ee 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -233,6 +233,7 @@ int ptrace_detach(struct task_struct *child, unsigned int data) | |||
233 | 233 | ||
234 | /* Architecture-specific hardware disable .. */ | 234 | /* Architecture-specific hardware disable .. */ |
235 | ptrace_disable(child); | 235 | ptrace_disable(child); |
236 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
236 | 237 | ||
237 | write_lock_irq(&tasklist_lock); | 238 | write_lock_irq(&tasklist_lock); |
238 | /* protect against de_thread()->release_task() */ | 239 | /* protect against de_thread()->release_task() */ |