Commit 52ee2dfdd4f51cf422ea6a96a0846dc94244aa37
Committed by
Linus Torvalds
1 parent
2ae448efc8
Exists in
master
and in
39 other branches
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 |
kernel/pid.c
... | ... | @@ -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 | { |