kernel/fork.c:copy_process(): don't add the uninitialized child to thread/task/pid lists
copy_process() adds the new child to thread_group/init_task.tasks list and then does attach_pid(child, PIDTYPE_PID). This means that the lockless next_thread() or next_task() can see this thread with the wrong pid. Say, "ls /proc/pid/task" can list the same inode twice. We could move attach_pid(child, PIDTYPE_PID) up, but in this case find_task_by_vpid() can find the new thread before it was fully initialized. And this is already true for PIDTYPE_PGID/PIDTYPE_SID, With this patch copy_process() initializes child->pids[*].pid first, then calls attach_pid() to insert the task into the pid->tasks list. attach_pid() no longer need the "struct pid*" argument, it is always called after pid_link->pid was already set. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Michal Hocko <mhocko@suse.cz> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Sergey Dyasly <dserrg@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
committed by
Linus Torvalds
parent
80628ca06c
commit
8190773985
12
kernel/pid.c
12
kernel/pid.c
@@ -373,14 +373,10 @@ EXPORT_SYMBOL_GPL(find_vpid);
|
||||
/*
|
||||
* attach_pid() must be called with the tasklist_lock write-held.
|
||||
*/
|
||||
void attach_pid(struct task_struct *task, enum pid_type type,
|
||||
struct pid *pid)
|
||||
void attach_pid(struct task_struct *task, enum pid_type type)
|
||||
{
|
||||
struct pid_link *link;
|
||||
|
||||
link = &task->pids[type];
|
||||
link->pid = pid;
|
||||
hlist_add_head_rcu(&link->node, &pid->tasks[type]);
|
||||
struct pid_link *link = &task->pids[type];
|
||||
hlist_add_head_rcu(&link->node, &link->pid->tasks[type]);
|
||||
}
|
||||
|
||||
static void __change_pid(struct task_struct *task, enum pid_type type,
|
||||
@@ -412,7 +408,7 @@ void change_pid(struct task_struct *task, enum pid_type type,
|
||||
struct pid *pid)
|
||||
{
|
||||
__change_pid(task, type, pid);
|
||||
attach_pid(task, type, pid);
|
||||
attach_pid(task, type);
|
||||
}
|
||||
|
||||
/* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
|
||||
|
Reference in New Issue
Block a user