[PATCH] introduce get_task_pid() to fix unsafe get_pid()
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>
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a317eb2..82da55b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -958,7 +958,7 @@
/*
* 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 @@
/*
* 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;
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 7e39767..17b9e04 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -68,6 +68,8 @@
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.
diff --git a/kernel/pid.c b/kernel/pid.c
index e4779bb..b914392 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -304,6 +304,15 @@
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;