aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2009-04-02 19:58:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-02 22:05:02 -0400
commit52ee2dfdd4f51cf422ea6a96a0846dc94244aa37 (patch)
treee15753e01d2c2fbe980edc45f78a9ae77d2cf891
parent2ae448efc87df6d328f5835969076c7f9fce59c3 (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>
-rw-r--r--include/linux/sched.h27
-rw-r--r--kernel/pid.c31
2 files changed, 36 insertions, 22 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 722dd313bf8a..49df878a0cad 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1519,17 +1519,23 @@ struct pid_namespace;
1519 * 1519 *
1520 * see also pid_nr() etc in include/linux/pid.h 1520 * see also pid_nr() etc in include/linux/pid.h
1521 */ 1521 */
1522pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
1523 struct pid_namespace *ns);
1522 1524
1523static inline pid_t task_pid_nr(struct task_struct *tsk) 1525static inline pid_t task_pid_nr(struct task_struct *tsk)
1524{ 1526{
1525 return tsk->pid; 1527 return tsk->pid;
1526} 1528}
1527 1529
1528pid_t task_pid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns); 1530static inline pid_t task_pid_nr_ns(struct task_struct *tsk,
1531 struct pid_namespace *ns)
1532{
1533 return __task_pid_nr_ns(tsk, PIDTYPE_PID, ns);
1534}
1529 1535
1530static inline pid_t task_pid_vnr(struct task_struct *tsk) 1536static inline pid_t task_pid_vnr(struct task_struct *tsk)
1531{ 1537{
1532 return pid_vnr(task_pid(tsk)); 1538 return __task_pid_nr_ns(tsk, PIDTYPE_PID, NULL);
1533} 1539}
1534 1540
1535 1541
@@ -1551,11 +1557,15 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk)
1551 return tsk->signal->__pgrp; 1557 return tsk->signal->__pgrp;
1552} 1558}
1553 1559
1554pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns); 1560static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk,
1561 struct pid_namespace *ns)
1562{
1563 return __task_pid_nr_ns(tsk, PIDTYPE_PGID, ns);
1564}
1555 1565
1556static inline pid_t task_pgrp_vnr(struct task_struct *tsk) 1566static inline pid_t task_pgrp_vnr(struct task_struct *tsk)
1557{ 1567{
1558 return pid_vnr(task_pgrp(tsk)); 1568 return __task_pid_nr_ns(tsk, PIDTYPE_PGID, NULL);
1559} 1569}
1560 1570
1561 1571
@@ -1564,14 +1574,17 @@ static inline pid_t task_session_nr(struct task_struct *tsk)
1564 return tsk->signal->__session; 1574 return tsk->signal->__session;
1565} 1575}
1566 1576
1567pid_t task_session_nr_ns(struct task_struct *tsk, struct pid_namespace *ns); 1577static inline pid_t task_session_nr_ns(struct task_struct *tsk,
1578 struct pid_namespace *ns)
1579{
1580 return __task_pid_nr_ns(tsk, PIDTYPE_SID, ns);
1581}
1568 1582
1569static inline pid_t task_session_vnr(struct task_struct *tsk) 1583static inline pid_t task_session_vnr(struct task_struct *tsk)
1570{ 1584{
1571 return pid_vnr(task_session(tsk)); 1585 return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL);
1572} 1586}
1573 1587
1574
1575/** 1588/**
1576 * pid_alive - check that a task structure is not stale 1589 * pid_alive - check that a task structure is not stale
1577 * @p: Task structure to be checked. 1590 * @p: Task structure to be checked.
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}
453EXPORT_SYMBOL_GPL(pid_vnr); 453EXPORT_SYMBOL_GPL(pid_vnr);
454 454
455pid_t task_pid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) 455pid_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}
459EXPORT_SYMBOL(task_pid_nr_ns); 472EXPORT_SYMBOL(__task_pid_nr_ns);
460 473
461pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns) 474pid_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}
465EXPORT_SYMBOL(task_tgid_nr_ns); 478EXPORT_SYMBOL(task_tgid_nr_ns);
466 479
467pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
468{
469 return pid_nr_ns(task_pgrp(tsk), ns);
470}
471EXPORT_SYMBOL(task_pgrp_nr_ns);
472
473pid_t task_session_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
474{
475 return pid_nr_ns(task_session(tsk), ns);
476}
477EXPORT_SYMBOL(task_session_nr_ns);
478
479struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) 480struct 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));