From: Oleg Nesterov Date: Wed, 30 Apr 2008 07:54:25 +0000 (-0700) Subject: pids: de_thread: don't clear session/pgrp pids for the old leader X-Git-Tag: firefly_0821_release~20644 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=65450cebc6a2efde80ed45514f727e6e4dc1eafd;p=firefly-linux-kernel-4.4.55.git pids: de_thread: don't clear session/pgrp pids for the old leader Based on Eric W. Biederman's idea. Unless task == current, without tasklist_lock held task_session()/task_pgrp() can return NULL if the caller races with de_thread() which switches the group leader. Change transfer_pid() to not clear old->pids[type].pid for the old leader. This means that its .pid can point to "nowhere", but this is already true for sub-threads, and the old leader is not group_leader() any longer. IOW, with or without this change we can't trust task's special pids unless it is the group leader. With this change the following code rcu_read_lock(); task = find_task_by_xxx(); do_something(task_pgrp(task), task_session(task)); rcu_read_unlock(); can't race with exec and hit the NULL pid. Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Cc: Pavel Emelyanov Cc: Roland McGrath Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/kernel/pid.c b/kernel/pid.c index a9ae9f7fb229..e9a31d362b28 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -354,7 +354,6 @@ void transfer_pid(struct task_struct *old, struct task_struct *new, { new->pids[type].pid = old->pids[type].pid; hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node); - old->pids[type].pid = NULL; } struct task_struct *pid_task(struct pid *pid, enum pid_type type)