[PATCH] introduce get_task_pid() to fix unsafe get_pid()
authorOleg Nesterov <oleg@tv-sign.ru>
Mon, 2 Oct 2006 09:18:59 +0000 (02:18 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 2 Oct 2006 14:57:25 +0000 (07:57 -0700)
proc_pid_make_inode:

ei->pid = get_pid(task_pid(task));

I think this is not safe.  get_pid() can be preempted after checking "pid
!= NULL".  Then the task exits, does detach_pid(), and RCU frees the pid.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/proc/base.c
include/linux/pid.h
kernel/pid.c

index a317eb2..82da55b 100644 (file)
@@ -958,7 +958,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
        /*
         * grab the reference to task.
         */
-       ei->pid = get_pid(task_pid(task));
+       ei->pid = get_task_pid(task, PIDTYPE_PID);
        if (!ei->pid)
                goto out_unlock;
 
@@ -1677,7 +1677,7 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
        /*
         * grab the reference to the task.
         */
-       ei->pid = get_pid(task_pid(task));
+       ei->pid = get_task_pid(task, PIDTYPE_PID);
        if (!ei->pid)
                goto out_iput;
 
index 7e39767..17b9e04 100644 (file)
@@ -68,6 +68,8 @@ extern struct task_struct *FASTCALL(pid_task(struct pid *pid, enum pid_type));
 extern struct task_struct *FASTCALL(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.
index e4779bb..b914392 100644 (file)
@@ -304,6 +304,15 @@ struct task_struct *find_task_by_pid_type(int type, int nr)
 
 EXPORT_SYMBOL(find_task_by_pid_type);
 
+struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
+{
+       struct pid *pid;
+       rcu_read_lock();
+       pid = get_pid(task->pids[type].pid);
+       rcu_read_unlock();
+       return pid;
+}
+
 struct task_struct *fastcall get_pid_task(struct pid *pid, enum pid_type type)
 {
        struct task_struct *result;