aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorBadari Pulavarty <pbadari@us.ibm.com>2007-05-08 03:25:21 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:00 -0400
commite3222c4ecc649c4ae568e61dda9349482401b501 (patch)
treed96614ef67d947a3dd8ab0929a4755bce9fdbcc1 /kernel/fork.c
parent4fc75ff4816c3483b4b772b2f6cb3d8fd88ca547 (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.c85
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 */
1521static 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 */
1541static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp) 1521static 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
1597static 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
1719bad_unshare_cleanup_ipc:
1720 if (new_ipc)
1721 put_ipc_ns(new_ipc);
1722
1723bad_unshare_cleanup_uts:
1724 if (new_uts)
1725 put_uts_ns(new_uts);
1726
1727bad_unshare_cleanup_semundo: 1656bad_unshare_cleanup_semundo:
1728bad_unshare_cleanup_fd: 1657bad_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
1741bad_unshare_cleanup_ns:
1742 if (new_ns)
1743 put_mnt_ns(new_ns);
1744
1745bad_unshare_cleanup_fs: 1670bad_unshare_cleanup_fs:
1746 if (new_fs) 1671 if (new_fs)
1747 put_fs_struct(new_fs); 1672 put_fs_struct(new_fs);