aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2009-12-15 19:47:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 10:20:08 -0500
commit6580807da14c423f0d0a708108e6df6ebc8bc83d (patch)
tree553e2de8f2174f9bbb6ab9a2454b1306bb5eb4fa /kernel/fork.c
parentc6a47cc2ccf9649ee09eeddd70a6d061bde69568 (diff)
ptrace: copy_process() should disable stepping
If the tracee calls fork() after PTRACE_SINGLESTEP, the forked child starts with TIF_SINGLESTEP/X86_EFLAGS_TF bits copied from ptraced parent. This is not right, especially when the new child is not auto-attaced: in this case it is killed by SIGTRAP. Change copy_process() to call user_disable_single_step(). Tested on x86. Test-case: #include <stdio.h> #include <unistd.h> #include <signal.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <assert.h> int main(void) { int pid, status; if (!(pid = fork())) { assert(ptrace(PTRACE_TRACEME) == 0); kill(getpid(), SIGSTOP); if (!fork()) { /* kernel bug: this child will be killed by SIGTRAP */ printf("Hello world\n"); return 43; } wait(&status); return WEXITSTATUS(status); } for (;;) { assert(pid == wait(&status)); if (WIFEXITED(status)) break; assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); } assert(WEXITSTATUS(status) == 43); return 0; } Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Roland McGrath <roland@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index b6cbd33dde80..202a0ba63d3c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1210,9 +1210,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1210 p->sas_ss_sp = p->sas_ss_size = 0; 1210 p->sas_ss_sp = p->sas_ss_size = 0;
1211 1211
1212 /* 1212 /*
1213 * Syscall tracing should be turned off in the child regardless 1213 * Syscall tracing and stepping should be turned off in the
1214 * of CLONE_PTRACE. 1214 * child regardless of CLONE_PTRACE.
1215 */ 1215 */
1216 user_disable_single_step(p);
1216 clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); 1217 clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
1217#ifdef TIF_SYSCALL_EMU 1218#ifdef TIF_SYSCALL_EMU
1218 clear_tsk_thread_flag(p, TIF_SYSCALL_EMU); 1219 clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);