Commit 52ee2dfdd4f51cf422ea6a96a0846dc94244aa37

Authored by Oleg Nesterov
Committed by Linus Torvalds
1 parent 2ae448efc8

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>

Showing 2 changed files with 36 additions and 22 deletions Side-by-side Diff

include/linux/sched.h
... ... @@ -1519,17 +1519,23 @@
1519 1519 *
1520 1520 * see also pid_nr() etc in include/linux/pid.h
1521 1521 */
  1522 +pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
  1523 + struct pid_namespace *ns);
1522 1524  
1523 1525 static inline pid_t task_pid_nr(struct task_struct *tsk)
1524 1526 {
1525 1527 return tsk->pid;
1526 1528 }
1527 1529  
1528   -pid_t task_pid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
  1530 +static 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  
1530 1536 static 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  
1536 1542  
... ... @@ -1551,11 +1557,15 @@
1551 1557 return tsk->signal->__pgrp;
1552 1558 }
1553 1559  
1554   -pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
  1560 +static 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  
1556 1566 static 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  
1562 1572  
1563 1573  
... ... @@ -1564,13 +1574,16 @@
1564 1574 return tsk->signal->__session;
1565 1575 }
1566 1576  
1567   -pid_t task_session_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
  1577 +static 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  
1569 1583 static 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   -
1574 1587  
1575 1588 /**
1576 1589 * pid_alive - check that a task structure is not stale
... ... @@ -452,29 +452,30 @@
452 452 }
453 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 474 pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
462 475 {
463 476 return pid_nr_ns(task_tgid(tsk), ns);
464 477 }
465 478 EXPORT_SYMBOL(task_tgid_nr_ns);
466   -
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  
479 480 struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
480 481 {