diff options
author | Badari Pulavarty <pbadari@us.ibm.com> | 2007-05-08 03:25:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:00 -0400 |
commit | e3222c4ecc649c4ae568e61dda9349482401b501 (patch) | |
tree | d96614ef67d947a3dd8ab0929a4755bce9fdbcc1 /kernel/fork.c | |
parent | 4fc75ff4816c3483b4b772b2f6cb3d8fd88ca547 (diff) |
Merge sys_clone()/sys_unshare() nsproxy and namespace handling
sys_clone() and sys_unshare() both makes copies of nsproxy and its associated
namespaces. But they have different code paths.
This patch merges all the nsproxy and its associated namespace copy/clone
handling (as much as possible). Posted on container list earlier for
feedback.
- Create a new nsproxy and its associated namespaces and pass it back to
caller to attach it to right process.
- Changed all copy_*_ns() routines to return a new copy of namespace
instead of attaching it to task->nsproxy.
- Moved the CAP_SYS_ADMIN checks out of copy_*_ns() routines.
- Removed unnessary !ns checks from copy_*_ns() and added BUG_ON()
just incase.
- Get rid of all individual unshare_*_ns() routines and make use of
copy_*_ns() instead.
[akpm@osdl.org: cleanups, warning fix]
[clg@fr.ibm.com: remove dup_namespaces() declaration]
[serue@us.ibm.com: fix CONFIG_IPC_NS=n, clone(CLONE_NEWIPC) retval]
[akpm@linux-foundation.org: fix build with CONFIG_SYSVIPC=n]
Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Signed-off-by: Serge Hallyn <serue@us.ibm.com>
Cc: Cedric Le Goater <clg@fr.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: <containers@lists.osdl.org>
Signed-off-by: Cedric Le Goater <clg@fr.ibm.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 85 |
1 files changed, 5 insertions, 80 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index b7d169def942..fd211b9dddd4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1516,26 +1516,6 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) | |||
1516 | } | 1516 | } |
1517 | 1517 | ||
1518 | /* | 1518 | /* |
1519 | * Unshare the mnt_namespace structure if it is being shared | ||
1520 | */ | ||
1521 | static int unshare_mnt_namespace(unsigned long unshare_flags, | ||
1522 | struct mnt_namespace **new_nsp, struct fs_struct *new_fs) | ||
1523 | { | ||
1524 | struct mnt_namespace *ns = current->nsproxy->mnt_ns; | ||
1525 | |||
1526 | if ((unshare_flags & CLONE_NEWNS) && ns) { | ||
1527 | if (!capable(CAP_SYS_ADMIN)) | ||
1528 | return -EPERM; | ||
1529 | |||
1530 | *new_nsp = dup_mnt_ns(current, new_fs ? new_fs : current->fs); | ||
1531 | if (!*new_nsp) | ||
1532 | return -ENOMEM; | ||
1533 | } | ||
1534 | |||
1535 | return 0; | ||
1536 | } | ||
1537 | |||
1538 | /* | ||
1539 | * Unsharing of sighand is not supported yet | 1519 | * Unsharing of sighand is not supported yet |
1540 | */ | 1520 | */ |
1541 | static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp) | 1521 | static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp) |
@@ -1593,16 +1573,6 @@ static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **n | |||
1593 | return 0; | 1573 | return 0; |
1594 | } | 1574 | } |
1595 | 1575 | ||
1596 | #ifndef CONFIG_IPC_NS | ||
1597 | static inline int unshare_ipcs(unsigned long flags, struct ipc_namespace **ns) | ||
1598 | { | ||
1599 | if (flags & CLONE_NEWIPC) | ||
1600 | return -EINVAL; | ||
1601 | |||
1602 | return 0; | ||
1603 | } | ||
1604 | #endif | ||
1605 | |||
1606 | /* | 1576 | /* |
1607 | * unshare allows a process to 'unshare' part of the process | 1577 | * unshare allows a process to 'unshare' part of the process |
1608 | * context which was originally shared using clone. copy_* | 1578 | * context which was originally shared using clone. copy_* |
@@ -1615,14 +1585,11 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1615 | { | 1585 | { |
1616 | int err = 0; | 1586 | int err = 0; |
1617 | struct fs_struct *fs, *new_fs = NULL; | 1587 | struct fs_struct *fs, *new_fs = NULL; |
1618 | struct mnt_namespace *ns, *new_ns = NULL; | ||
1619 | struct sighand_struct *new_sigh = NULL; | 1588 | struct sighand_struct *new_sigh = NULL; |
1620 | struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; | 1589 | struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL; |
1621 | struct files_struct *fd, *new_fd = NULL; | 1590 | struct files_struct *fd, *new_fd = NULL; |
1622 | struct sem_undo_list *new_ulist = NULL; | 1591 | struct sem_undo_list *new_ulist = NULL; |
1623 | struct nsproxy *new_nsproxy = NULL, *old_nsproxy = NULL; | 1592 | struct nsproxy *new_nsproxy = NULL, *old_nsproxy = NULL; |
1624 | struct uts_namespace *uts, *new_uts = NULL; | ||
1625 | struct ipc_namespace *ipc, *new_ipc = NULL; | ||
1626 | 1593 | ||
1627 | check_unshare_flags(&unshare_flags); | 1594 | check_unshare_flags(&unshare_flags); |
1628 | 1595 | ||
@@ -1637,36 +1604,24 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1637 | goto bad_unshare_out; | 1604 | goto bad_unshare_out; |
1638 | if ((err = unshare_fs(unshare_flags, &new_fs))) | 1605 | if ((err = unshare_fs(unshare_flags, &new_fs))) |
1639 | goto bad_unshare_cleanup_thread; | 1606 | goto bad_unshare_cleanup_thread; |
1640 | if ((err = unshare_mnt_namespace(unshare_flags, &new_ns, new_fs))) | ||
1641 | goto bad_unshare_cleanup_fs; | ||
1642 | if ((err = unshare_sighand(unshare_flags, &new_sigh))) | 1607 | if ((err = unshare_sighand(unshare_flags, &new_sigh))) |
1643 | goto bad_unshare_cleanup_ns; | 1608 | goto bad_unshare_cleanup_fs; |
1644 | if ((err = unshare_vm(unshare_flags, &new_mm))) | 1609 | if ((err = unshare_vm(unshare_flags, &new_mm))) |
1645 | goto bad_unshare_cleanup_sigh; | 1610 | goto bad_unshare_cleanup_sigh; |
1646 | if ((err = unshare_fd(unshare_flags, &new_fd))) | 1611 | if ((err = unshare_fd(unshare_flags, &new_fd))) |
1647 | goto bad_unshare_cleanup_vm; | 1612 | goto bad_unshare_cleanup_vm; |
1648 | if ((err = unshare_semundo(unshare_flags, &new_ulist))) | 1613 | if ((err = unshare_semundo(unshare_flags, &new_ulist))) |
1649 | goto bad_unshare_cleanup_fd; | 1614 | goto bad_unshare_cleanup_fd; |
1650 | if ((err = unshare_utsname(unshare_flags, &new_uts))) | 1615 | if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, |
1616 | new_fs))) | ||
1651 | goto bad_unshare_cleanup_semundo; | 1617 | goto bad_unshare_cleanup_semundo; |
1652 | if ((err = unshare_ipcs(unshare_flags, &new_ipc))) | ||
1653 | goto bad_unshare_cleanup_uts; | ||
1654 | |||
1655 | if (new_ns || new_uts || new_ipc) { | ||
1656 | old_nsproxy = current->nsproxy; | ||
1657 | new_nsproxy = dup_namespaces(old_nsproxy); | ||
1658 | if (!new_nsproxy) { | ||
1659 | err = -ENOMEM; | ||
1660 | goto bad_unshare_cleanup_ipc; | ||
1661 | } | ||
1662 | } | ||
1663 | 1618 | ||
1664 | if (new_fs || new_ns || new_mm || new_fd || new_ulist || | 1619 | if (new_fs || new_mm || new_fd || new_ulist || new_nsproxy) { |
1665 | new_uts || new_ipc) { | ||
1666 | 1620 | ||
1667 | task_lock(current); | 1621 | task_lock(current); |
1668 | 1622 | ||
1669 | if (new_nsproxy) { | 1623 | if (new_nsproxy) { |
1624 | old_nsproxy = current->nsproxy; | ||
1670 | current->nsproxy = new_nsproxy; | 1625 | current->nsproxy = new_nsproxy; |
1671 | new_nsproxy = old_nsproxy; | 1626 | new_nsproxy = old_nsproxy; |
1672 | } | 1627 | } |
@@ -1677,12 +1632,6 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1677 | new_fs = fs; | 1632 | new_fs = fs; |
1678 | } | 1633 | } |
1679 | 1634 | ||
1680 | if (new_ns) { | ||
1681 | ns = current->nsproxy->mnt_ns; | ||
1682 | current->nsproxy->mnt_ns = new_ns; | ||
1683 | new_ns = ns; | ||
1684 | } | ||
1685 | |||
1686 | if (new_mm) { | 1635 | if (new_mm) { |
1687 | mm = current->mm; | 1636 | mm = current->mm; |
1688 | active_mm = current->active_mm; | 1637 | active_mm = current->active_mm; |
@@ -1698,32 +1647,12 @@ asmlinkage long sys_unshare(unsigned long unshare_flags) | |||
1698 | new_fd = fd; | 1647 | new_fd = fd; |
1699 | } | 1648 | } |
1700 | 1649 | ||
1701 | if (new_uts) { | ||
1702 | uts = current->nsproxy->uts_ns; | ||
1703 | current->nsproxy->uts_ns = new_uts; | ||
1704 | new_uts = uts; | ||
1705 | } | ||
1706 | |||
1707 | if (new_ipc) { | ||
1708 | ipc = current->nsproxy->ipc_ns; | ||
1709 | current->nsproxy->ipc_ns = new_ipc; | ||
1710 | new_ipc = ipc; | ||
1711 | } | ||
1712 | |||
1713 | task_unlock(current); | 1650 | task_unlock(current); |
1714 | } | 1651 | } |
1715 | 1652 | ||
1716 | if (new_nsproxy) | 1653 | if (new_nsproxy) |
1717 | put_nsproxy(new_nsproxy); | 1654 | put_nsproxy(new_nsproxy); |
1718 | 1655 | ||
1719 | bad_unshare_cleanup_ipc: | ||
1720 | if (new_ipc) | ||
1721 | put_ipc_ns(new_ipc); | ||
1722 | |||
1723 | bad_unshare_cleanup_uts: | ||
1724 | if (new_uts) | ||
1725 | put_uts_ns(new_uts); | ||
1726 | |||
1727 | bad_unshare_cleanup_semundo: | 1656 | bad_unshare_cleanup_semundo: |
1728 | bad_unshare_cleanup_fd: | 1657 | bad_unshare_cleanup_fd: |
1729 | if (new_fd) | 1658 | if (new_fd) |
@@ -1738,10 +1667,6 @@ bad_unshare_cleanup_sigh: | |||
1738 | if (atomic_dec_and_test(&new_sigh->count)) | 1667 | if (atomic_dec_and_test(&new_sigh->count)) |
1739 | kmem_cache_free(sighand_cachep, new_sigh); | 1668 | kmem_cache_free(sighand_cachep, new_sigh); |
1740 | 1669 | ||
1741 | bad_unshare_cleanup_ns: | ||
1742 | if (new_ns) | ||
1743 | put_mnt_ns(new_ns); | ||
1744 | |||
1745 | bad_unshare_cleanup_fs: | 1670 | bad_unshare_cleanup_fs: |
1746 | if (new_fs) | 1671 | if (new_fs) |
1747 | put_fs_struct(new_fs); | 1672 | put_fs_struct(new_fs); |