lkml.org 
[lkml]   [2008]   [Mar]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH 2/4] pids: introduce change_pid() helper
Based on Eric W. Biederman's idea.

Without tasklist_lock held task_session()/task_pgrp() can return NULL if the
caller races with setprgp()/setsid() which does detach_pid() + attach_pid().
This can happen even if task == current.

Intoduce the new helper, change_pid(), which should be used instead. This way
the caller always sees the special pid != NULL, either old or new.

Also change the prototype of attach_pid(), it always returns 0 and nobody check
the returned value.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>

--- 25/include/linux/pid.h~2_PID_CHANGE 2008-03-20 18:02:22.000000000 +0300
+++ 25/include/linux/pid.h 2008-03-20 18:07:37.000000000 +0300
@@ -89,9 +89,11 @@ extern struct pid *get_task_pid(struct t
* attach_pid() and detach_pid() must be called with the tasklist_lock
* write-held.
*/
-extern int attach_pid(struct task_struct *task, enum pid_type type,
- struct pid *pid);
+extern void attach_pid(struct task_struct *task, enum pid_type type,
+ struct pid *pid);
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);
extern void transfer_pid(struct task_struct *old, struct task_struct *new,
enum pid_type);

--- 25/kernel/pid.c~2_PID_CHANGE 2008-03-20 17:22:19.000000000 +0300
+++ 25/kernel/pid.c 2008-03-20 18:04:28.000000000 +0300
@@ -317,7 +317,7 @@ EXPORT_SYMBOL_GPL(find_pid);
/*
* attach_pid() must be called with the tasklist_lock write-held.
*/
-int attach_pid(struct task_struct *task, enum pid_type type,
+void attach_pid(struct task_struct *task, enum pid_type type,
struct pid *pid)
{
struct pid_link *link;
@@ -325,11 +325,10 @@ int attach_pid(struct task_struct *task,
link = &task->pids[type];
link->pid = pid;
hlist_add_head_rcu(&link->node, &pid->tasks[type]);
-
- return 0;
}

-void detach_pid(struct task_struct *task, enum pid_type type)
+static void __change_pid(struct task_struct *task, enum pid_type type,
+ struct pid *new)
{
struct pid_link *link;
struct pid *pid;
@@ -339,7 +338,7 @@ void detach_pid(struct task_struct *task
pid = link->pid;

hlist_del_rcu(&link->node);
- link->pid = NULL;
+ link->pid = new;

for (tmp = PIDTYPE_MAX; --tmp >= 0; )
if (!hlist_empty(&pid->tasks[tmp]))
@@ -348,6 +347,18 @@ void detach_pid(struct task_struct *task
free_pid(pid);
}

+void detach_pid(struct task_struct *task, enum pid_type type)
+{
+ __change_pid(task, type, NULL);
+}
+
+void change_pid(struct task_struct *task, enum pid_type type,
+ struct pid *pid)
+{
+ __change_pid(task, type, pid);
+ attach_pid(task, type, pid);
+}
+
/* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
void transfer_pid(struct task_struct *old, struct task_struct *new,
enum pid_type type)


\
 
 \ /
  Last update: 2008-03-20 16:27    [W:0.028 / U:0.120 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site