From: Daniel Jacobowitz Fix http://bugzilla.kernel.org/show_bug.cgi?id=7210 Do not implement CLONE_PARENT_SETTID until we know that clone will succeed. If we do it too early NPTL's data structures temporarily reference a non-existant TID. Signed-off-by: Daniel Jacobowitz Cc: "Eric W. Biederman" Acked-by: Roland McGrath Cc: Oleg Nesterov Signed-off-by: Andrew Morton --- kernel/fork.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff -puN kernel/fork.c~clone-flag-clone_parent_tidptr-leaves-invalid-results-in-memory kernel/fork.c --- a/kernel/fork.c~clone-flag-clone_parent_tidptr-leaves-invalid-results-in-memory +++ a/kernel/fork.c @@ -1025,11 +1025,6 @@ static struct task_struct *copy_process( delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ copy_flags(clone_flags, p); p->pid = pid_nr(pid); - retval = -EFAULT; - if (clone_flags & CLONE_PARENT_SETTID) - if (put_user(p->pid, parent_tidptr)) - goto bad_fork_cleanup_delays_binfmt; - INIT_LIST_HEAD(&p->children); INIT_LIST_HEAD(&p->sibling); p->vfork_done = NULL; @@ -1266,6 +1261,14 @@ static struct task_struct *copy_process( total_forks++; spin_unlock(¤t->sighand->siglock); write_unlock_irq(&tasklist_lock); + + /* + * Now that we know the fork has succeeded, record the new + * TID. It's too late to back out if this fails. + */ + if (clone_flags & CLONE_PARENT_SETTID) + put_user(p->pid, parent_tidptr); + proc_fork_connector(p); return p; @@ -1296,7 +1299,6 @@ bad_fork_cleanup_policy: bad_fork_cleanup_cpuset: #endif cpuset_exit(p); -bad_fork_cleanup_delays_binfmt: delayacct_tsk_free(p); if (p->binfmt) module_put(p->binfmt->module); _