From: Oleg Nesterov <oleg@redhat.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>,
Michal Hocko <mhocko@suse.cz>,
Pavel Emelyanov <xemul@parallels.com>,
Sergey Dyasly <dserrg@gmail.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH 3/4] copy_process: don't add the uninitialized child to thread/task/pid lists
Date: Sun, 9 Jun 2013 19:00:28 +0200 [thread overview]
Message-ID: <20130609170028.GA5243@redhat.com> (raw)
In-Reply-To: <20130609170007.GA5215@redhat.com>
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>
---
include/linux/pid.h | 6 ++----
kernel/fork.c | 16 +++++++++++++---
kernel/pid.c | 12 ++++--------
3 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/include/linux/pid.h b/include/linux/pid.h
index a089a3c..23705a5 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -86,11 +86,9 @@ extern struct task_struct *get_pid_task(struct pid *pid, enum pid_type);
extern struct pid *get_task_pid(struct task_struct *task, enum pid_type type);
/*
- * attach_pid() and detach_pid() must be called with the tasklist_lock
- * write-held.
+ * these helpers must be called with the tasklist_lock write-held.
*/
-extern void attach_pid(struct task_struct *task, enum pid_type type,
- struct pid *pid);
+extern void attach_pid(struct task_struct *task, enum pid_type);
extern void detach_pid(struct task_struct *task, enum pid_type);
extern void change_pid(struct task_struct *task, enum pid_type,
struct pid *pid);
diff --git a/kernel/fork.c b/kernel/fork.c
index 7bc4146..c836e3c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1121,6 +1121,12 @@ static void posix_cpu_timers_init(struct task_struct *tsk)
INIT_LIST_HEAD(&tsk->cpu_timers[2]);
}
+static inline void
+init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid)
+{
+ task->pids[type].pid = pid;
+}
+
/*
* This creates a new process as a copy of the old one,
* but does not actually start it yet.
@@ -1449,7 +1455,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
if (likely(p->pid)) {
ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
+ init_task_pid(p, PIDTYPE_PID, pid);
if (thread_group_leader(p)) {
+ init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));
+ init_task_pid(p, PIDTYPE_SID, task_session(current));
+
if (is_child_reaper(pid)) {
ns_of_pid(pid)->child_reaper = p;
p->signal->flags |= SIGNAL_UNKILLABLE;
@@ -1457,10 +1467,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->signal->leader_pid = pid;
p->signal->tty = tty_kref_get(current->signal->tty);
- attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
- attach_pid(p, PIDTYPE_SID, task_session(current));
list_add_tail(&p->sibling, &p->real_parent->children);
list_add_tail_rcu(&p->tasks, &init_task.tasks);
+ attach_pid(p, PIDTYPE_PGID);
+ attach_pid(p, PIDTYPE_SID);
__this_cpu_inc(process_counts);
} else {
current->signal->nr_threads++;
@@ -1470,7 +1480,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
list_add_tail_rcu(&p->thread_group,
&p->group_leader->thread_group);
}
- attach_pid(p, PIDTYPE_PID, pid);
+ attach_pid(p, PIDTYPE_PID);
nr_threads++;
}
diff --git a/kernel/pid.c b/kernel/pid.c
index 0db3e79..61980ce 100644
--- a/kernel/pid.c
+++ b/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) */
--
1.5.5.1
next prev parent reply other threads:[~2013-06-09 17:04 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-09 17:00 [PATCH v2 0/4] copy_process/attach_pid minor fix + cleanups Oleg Nesterov
2013-06-09 17:00 ` [PATCH 1/4] de_thread: use change_pid() rather than detach_pid/attach_pid Oleg Nesterov
2013-06-10 4:07 ` Eric W. Biederman
2013-06-09 17:00 ` [PATCH 2/4] copy_process: unify CLONE_THREAD-or-thread_group_leader code Oleg Nesterov
2013-06-09 17:00 ` Oleg Nesterov [this message]
2013-06-09 17:00 ` [PATCH 4/4] copy_process: consolidate the lockless CLONE_THREAD checks Oleg Nesterov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130609170028.GA5243@redhat.com \
--to=oleg@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=dserrg@gmail.com \
--cc=ebiederm@xmission.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mhocko@suse.cz \
--cc=xemul@parallels.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.