mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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>
This commit is contained in:
parent
897ee77bfb
commit
7d94143291
4 changed files with 1 additions and 3 deletions
|
@ -274,7 +274,6 @@ static void clear_singlestep(struct task_struct *child)
|
||||||
void ptrace_disable(struct task_struct *child)
|
void ptrace_disable(struct task_struct *child)
|
||||||
{
|
{
|
||||||
clear_singlestep(child);
|
clear_singlestep(child);
|
||||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
|
||||||
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1577,7 +1577,6 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
|
||||||
|
|
||||||
case PTRACE_DETACH:
|
case PTRACE_DETACH:
|
||||||
/* detach a process that was attached. */
|
/* detach a process that was attached. */
|
||||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
|
||||||
ret = ptrace_detach(child, data);
|
ret = ptrace_detach(child, data);
|
||||||
goto out_tsk;
|
goto out_tsk;
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,6 @@ static inline void singlestep_disable(struct task_struct *child)
|
||||||
void ptrace_disable(struct task_struct *child)
|
void ptrace_disable(struct task_struct *child)
|
||||||
{
|
{
|
||||||
singlestep_disable(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)
|
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
|
|
|
@ -233,6 +233,7 @@ int ptrace_detach(struct task_struct *child, unsigned int data)
|
||||||
|
|
||||||
/* Architecture-specific hardware disable .. */
|
/* Architecture-specific hardware disable .. */
|
||||||
ptrace_disable(child);
|
ptrace_disable(child);
|
||||||
|
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||||
|
|
||||||
write_lock_irq(&tasklist_lock);
|
write_lock_irq(&tasklist_lock);
|
||||||
/* protect against de_thread()->release_task() */
|
/* protect against de_thread()->release_task() */
|
||||||
|
|
Loading…
Reference in a new issue