diff options
author | Oleg Nesterov <oleg@redhat.com> | 2009-04-02 19:58:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:05:02 -0400 |
commit | 52ee2dfdd4f51cf422ea6a96a0846dc94244aa37 (patch) | |
tree | e15753e01d2c2fbe980edc45f78a9ae77d2cf891 /kernel/pid.c | |
parent | 2ae448efc87df6d328f5835969076c7f9fce59c3 (diff) |
pids: refactor vnr/nr_ns helpers to make them safe
Inho, the safety rules for vnr/nr_ns helpers are horrible and buggy.
task_pid_nr_ns(task) needs rcu/tasklist depending on task == current.
As for "special" pids, vnr/nr_ns helpers always need rcu. However, if
task != current, they are unsafe even under rcu lock, we can't trust
task->group_leader without the special checks.
And almost every helper has a callsite which needs a fix.
Also, it is a bit annoying that the implementations of, say,
task_pgrp_vnr() and task_pgrp_nr_ns() are not "symmetrical".
This patch introduces the new helper, __task_pid_nr_ns(), which is always
safe to use, and turns all other helpers into the trivial wrappers.
After this I'll send another patch which converts task_tgid_xxx() as well,
they're are a bit special.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Louis Rilling <Louis.Rilling@kerlabs.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Pavel Emelyanov <xemul@openvz.org>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/pid.c')
-rw-r--r-- | kernel/pid.c | 31 |
1 files changed, 16 insertions, 15 deletions
diff --git a/kernel/pid.c b/kernel/pid.c index 6628abcc520e..b2e5f78fd281 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -452,11 +452,24 @@ pid_t pid_vnr(struct pid *pid) | |||
452 | } | 452 | } |
453 | EXPORT_SYMBOL_GPL(pid_vnr); | 453 | EXPORT_SYMBOL_GPL(pid_vnr); |
454 | 454 | ||
455 | pid_t task_pid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) | 455 | pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, |
456 | struct pid_namespace *ns) | ||
456 | { | 457 | { |
457 | return pid_nr_ns(task_pid(tsk), ns); | 458 | pid_t nr = 0; |
459 | |||
460 | rcu_read_lock(); | ||
461 | if (!ns) | ||
462 | ns = current->nsproxy->pid_ns; | ||
463 | if (likely(pid_alive(task))) { | ||
464 | if (type != PIDTYPE_PID) | ||
465 | task = task->group_leader; | ||
466 | nr = pid_nr_ns(task->pids[type].pid, ns); | ||
467 | } | ||
468 | rcu_read_unlock(); | ||
469 | |||
470 | return nr; | ||
458 | } | 471 | } |
459 | EXPORT_SYMBOL(task_pid_nr_ns); | 472 | EXPORT_SYMBOL(__task_pid_nr_ns); |
460 | 473 | ||
461 | pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) | 474 | pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) |
462 | { | 475 | { |
@@ -464,18 +477,6 @@ pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) | |||
464 | } | 477 | } |
465 | EXPORT_SYMBOL(task_tgid_nr_ns); | 478 | EXPORT_SYMBOL(task_tgid_nr_ns); |
466 | 479 | ||
467 | pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) | ||
468 | { | ||
469 | return pid_nr_ns(task_pgrp(tsk), ns); | ||
470 | } | ||
471 | EXPORT_SYMBOL(task_pgrp_nr_ns); | ||
472 | |||
473 | pid_t task_session_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) | ||
474 | { | ||
475 | return pid_nr_ns(task_session(tsk), ns); | ||
476 | } | ||
477 | EXPORT_SYMBOL(task_session_nr_ns); | ||
478 | |||
479 | struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) | 480 | struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) |
480 | { | 481 | { |
481 | return ns_of_pid(task_pid(tsk)); | 482 | return ns_of_pid(task_pid(tsk)); |