diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 355 |
1 files changed, 234 insertions, 121 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 7b0b95371696..7dba2ed03429 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -196,7 +196,7 @@ unsigned int mnt_get_count(struct vfsmount *mnt) | |||
196 | #endif | 196 | #endif |
197 | } | 197 | } |
198 | 198 | ||
199 | struct vfsmount *alloc_vfsmnt(const char *name) | 199 | static struct vfsmount *alloc_vfsmnt(const char *name) |
200 | { | 200 | { |
201 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); | 201 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); |
202 | if (mnt) { | 202 | if (mnt) { |
@@ -466,15 +466,7 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt) | |||
466 | br_write_unlock(vfsmount_lock); | 466 | br_write_unlock(vfsmount_lock); |
467 | } | 467 | } |
468 | 468 | ||
469 | void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) | 469 | static void free_vfsmnt(struct vfsmount *mnt) |
470 | { | ||
471 | mnt->mnt_sb = sb; | ||
472 | mnt->mnt_root = dget(sb->s_root); | ||
473 | } | ||
474 | |||
475 | EXPORT_SYMBOL(simple_set_mnt); | ||
476 | |||
477 | void free_vfsmnt(struct vfsmount *mnt) | ||
478 | { | 470 | { |
479 | kfree(mnt->mnt_devname); | 471 | kfree(mnt->mnt_devname); |
480 | mnt_free_id(mnt); | 472 | mnt_free_id(mnt); |
@@ -678,6 +670,36 @@ static struct vfsmount *skip_mnt_tree(struct vfsmount *p) | |||
678 | return p; | 670 | return p; |
679 | } | 671 | } |
680 | 672 | ||
673 | struct vfsmount * | ||
674 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) | ||
675 | { | ||
676 | struct vfsmount *mnt; | ||
677 | struct dentry *root; | ||
678 | |||
679 | if (!type) | ||
680 | return ERR_PTR(-ENODEV); | ||
681 | |||
682 | mnt = alloc_vfsmnt(name); | ||
683 | if (!mnt) | ||
684 | return ERR_PTR(-ENOMEM); | ||
685 | |||
686 | if (flags & MS_KERNMOUNT) | ||
687 | mnt->mnt_flags = MNT_INTERNAL; | ||
688 | |||
689 | root = mount_fs(type, flags, name, data); | ||
690 | if (IS_ERR(root)) { | ||
691 | free_vfsmnt(mnt); | ||
692 | return ERR_CAST(root); | ||
693 | } | ||
694 | |||
695 | mnt->mnt_root = root; | ||
696 | mnt->mnt_sb = root->d_sb; | ||
697 | mnt->mnt_mountpoint = mnt->mnt_root; | ||
698 | mnt->mnt_parent = mnt; | ||
699 | return mnt; | ||
700 | } | ||
701 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | ||
702 | |||
681 | static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | 703 | static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, |
682 | int flag) | 704 | int flag) |
683 | { | 705 | { |
@@ -978,7 +1000,13 @@ static int show_vfsmnt(struct seq_file *m, void *v) | |||
978 | int err = 0; | 1000 | int err = 0; |
979 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; | 1001 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; |
980 | 1002 | ||
981 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | 1003 | if (mnt->mnt_sb->s_op->show_devname) { |
1004 | err = mnt->mnt_sb->s_op->show_devname(m, mnt); | ||
1005 | if (err) | ||
1006 | goto out; | ||
1007 | } else { | ||
1008 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | ||
1009 | } | ||
982 | seq_putc(m, ' '); | 1010 | seq_putc(m, ' '); |
983 | seq_path(m, &mnt_path, " \t\n\\"); | 1011 | seq_path(m, &mnt_path, " \t\n\\"); |
984 | seq_putc(m, ' '); | 1012 | seq_putc(m, ' '); |
@@ -1002,6 +1030,18 @@ const struct seq_operations mounts_op = { | |||
1002 | .show = show_vfsmnt | 1030 | .show = show_vfsmnt |
1003 | }; | 1031 | }; |
1004 | 1032 | ||
1033 | static int uuid_is_nil(u8 *uuid) | ||
1034 | { | ||
1035 | int i; | ||
1036 | u8 *cp = (u8 *)uuid; | ||
1037 | |||
1038 | for (i = 0; i < 16; i++) { | ||
1039 | if (*cp++) | ||
1040 | return 0; | ||
1041 | } | ||
1042 | return 1; | ||
1043 | } | ||
1044 | |||
1005 | static int show_mountinfo(struct seq_file *m, void *v) | 1045 | static int show_mountinfo(struct seq_file *m, void *v) |
1006 | { | 1046 | { |
1007 | struct proc_mounts *p = m->private; | 1047 | struct proc_mounts *p = m->private; |
@@ -1013,7 +1053,12 @@ static int show_mountinfo(struct seq_file *m, void *v) | |||
1013 | 1053 | ||
1014 | seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id, | 1054 | seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id, |
1015 | MAJOR(sb->s_dev), MINOR(sb->s_dev)); | 1055 | MAJOR(sb->s_dev), MINOR(sb->s_dev)); |
1016 | seq_dentry(m, mnt->mnt_root, " \t\n\\"); | 1056 | if (sb->s_op->show_path) |
1057 | err = sb->s_op->show_path(m, mnt); | ||
1058 | else | ||
1059 | seq_dentry(m, mnt->mnt_root, " \t\n\\"); | ||
1060 | if (err) | ||
1061 | goto out; | ||
1017 | seq_putc(m, ' '); | 1062 | seq_putc(m, ' '); |
1018 | seq_path_root(m, &mnt_path, &root, " \t\n\\"); | 1063 | seq_path_root(m, &mnt_path, &root, " \t\n\\"); |
1019 | if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { | 1064 | if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { |
@@ -1040,11 +1085,20 @@ static int show_mountinfo(struct seq_file *m, void *v) | |||
1040 | if (IS_MNT_UNBINDABLE(mnt)) | 1085 | if (IS_MNT_UNBINDABLE(mnt)) |
1041 | seq_puts(m, " unbindable"); | 1086 | seq_puts(m, " unbindable"); |
1042 | 1087 | ||
1088 | if (!uuid_is_nil(mnt->mnt_sb->s_uuid)) | ||
1089 | /* print the uuid */ | ||
1090 | seq_printf(m, " uuid:%pU", mnt->mnt_sb->s_uuid); | ||
1091 | |||
1043 | /* Filesystem specific data */ | 1092 | /* Filesystem specific data */ |
1044 | seq_puts(m, " - "); | 1093 | seq_puts(m, " - "); |
1045 | show_type(m, sb); | 1094 | show_type(m, sb); |
1046 | seq_putc(m, ' '); | 1095 | seq_putc(m, ' '); |
1047 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | 1096 | if (sb->s_op->show_devname) |
1097 | err = sb->s_op->show_devname(m, mnt); | ||
1098 | else | ||
1099 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | ||
1100 | if (err) | ||
1101 | goto out; | ||
1048 | seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); | 1102 | seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); |
1049 | err = show_sb_opts(m, sb); | 1103 | err = show_sb_opts(m, sb); |
1050 | if (err) | 1104 | if (err) |
@@ -1070,11 +1124,15 @@ static int show_vfsstat(struct seq_file *m, void *v) | |||
1070 | int err = 0; | 1124 | int err = 0; |
1071 | 1125 | ||
1072 | /* device */ | 1126 | /* device */ |
1073 | if (mnt->mnt_devname) { | 1127 | if (mnt->mnt_sb->s_op->show_devname) { |
1074 | seq_puts(m, "device "); | 1128 | err = mnt->mnt_sb->s_op->show_devname(m, mnt); |
1075 | mangle(m, mnt->mnt_devname); | 1129 | } else { |
1076 | } else | 1130 | if (mnt->mnt_devname) { |
1077 | seq_puts(m, "no device"); | 1131 | seq_puts(m, "device "); |
1132 | mangle(m, mnt->mnt_devname); | ||
1133 | } else | ||
1134 | seq_puts(m, "no device"); | ||
1135 | } | ||
1078 | 1136 | ||
1079 | /* mount point */ | 1137 | /* mount point */ |
1080 | seq_puts(m, " mounted on "); | 1138 | seq_puts(m, " mounted on "); |
@@ -1088,7 +1146,8 @@ static int show_vfsstat(struct seq_file *m, void *v) | |||
1088 | /* optional statistics */ | 1146 | /* optional statistics */ |
1089 | if (mnt->mnt_sb->s_op->show_stats) { | 1147 | if (mnt->mnt_sb->s_op->show_stats) { |
1090 | seq_putc(m, ' '); | 1148 | seq_putc(m, ' '); |
1091 | err = mnt->mnt_sb->s_op->show_stats(m, mnt); | 1149 | if (!err) |
1150 | err = mnt->mnt_sb->s_op->show_stats(m, mnt); | ||
1092 | } | 1151 | } |
1093 | 1152 | ||
1094 | seq_putc(m, '\n'); | 1153 | seq_putc(m, '\n'); |
@@ -1244,7 +1303,7 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
1244 | */ | 1303 | */ |
1245 | br_write_lock(vfsmount_lock); | 1304 | br_write_lock(vfsmount_lock); |
1246 | if (mnt_get_count(mnt) != 2) { | 1305 | if (mnt_get_count(mnt) != 2) { |
1247 | br_write_lock(vfsmount_lock); | 1306 | br_write_unlock(vfsmount_lock); |
1248 | return -EBUSY; | 1307 | return -EBUSY; |
1249 | } | 1308 | } |
1250 | br_write_unlock(vfsmount_lock); | 1309 | br_write_unlock(vfsmount_lock); |
@@ -1604,9 +1663,35 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
1604 | return err; | 1663 | return err; |
1605 | } | 1664 | } |
1606 | 1665 | ||
1666 | static int lock_mount(struct path *path) | ||
1667 | { | ||
1668 | struct vfsmount *mnt; | ||
1669 | retry: | ||
1670 | mutex_lock(&path->dentry->d_inode->i_mutex); | ||
1671 | if (unlikely(cant_mount(path->dentry))) { | ||
1672 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
1673 | return -ENOENT; | ||
1674 | } | ||
1675 | down_write(&namespace_sem); | ||
1676 | mnt = lookup_mnt(path); | ||
1677 | if (likely(!mnt)) | ||
1678 | return 0; | ||
1679 | up_write(&namespace_sem); | ||
1680 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
1681 | path_put(path); | ||
1682 | path->mnt = mnt; | ||
1683 | path->dentry = dget(mnt->mnt_root); | ||
1684 | goto retry; | ||
1685 | } | ||
1686 | |||
1687 | static void unlock_mount(struct path *path) | ||
1688 | { | ||
1689 | up_write(&namespace_sem); | ||
1690 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
1691 | } | ||
1692 | |||
1607 | static int graft_tree(struct vfsmount *mnt, struct path *path) | 1693 | static int graft_tree(struct vfsmount *mnt, struct path *path) |
1608 | { | 1694 | { |
1609 | int err; | ||
1610 | if (mnt->mnt_sb->s_flags & MS_NOUSER) | 1695 | if (mnt->mnt_sb->s_flags & MS_NOUSER) |
1611 | return -EINVAL; | 1696 | return -EINVAL; |
1612 | 1697 | ||
@@ -1614,16 +1699,10 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) | |||
1614 | S_ISDIR(mnt->mnt_root->d_inode->i_mode)) | 1699 | S_ISDIR(mnt->mnt_root->d_inode->i_mode)) |
1615 | return -ENOTDIR; | 1700 | return -ENOTDIR; |
1616 | 1701 | ||
1617 | err = -ENOENT; | 1702 | if (d_unlinked(path->dentry)) |
1618 | mutex_lock(&path->dentry->d_inode->i_mutex); | 1703 | return -ENOENT; |
1619 | if (cant_mount(path->dentry)) | ||
1620 | goto out_unlock; | ||
1621 | 1704 | ||
1622 | if (!d_unlinked(path->dentry)) | 1705 | return attach_recursive_mnt(mnt, path, NULL); |
1623 | err = attach_recursive_mnt(mnt, path, NULL); | ||
1624 | out_unlock: | ||
1625 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
1626 | return err; | ||
1627 | } | 1706 | } |
1628 | 1707 | ||
1629 | /* | 1708 | /* |
@@ -1686,6 +1765,7 @@ static int do_change_type(struct path *path, int flag) | |||
1686 | static int do_loopback(struct path *path, char *old_name, | 1765 | static int do_loopback(struct path *path, char *old_name, |
1687 | int recurse) | 1766 | int recurse) |
1688 | { | 1767 | { |
1768 | LIST_HEAD(umount_list); | ||
1689 | struct path old_path; | 1769 | struct path old_path; |
1690 | struct vfsmount *mnt = NULL; | 1770 | struct vfsmount *mnt = NULL; |
1691 | int err = mount_is_safe(path); | 1771 | int err = mount_is_safe(path); |
@@ -1697,13 +1777,16 @@ static int do_loopback(struct path *path, char *old_name, | |||
1697 | if (err) | 1777 | if (err) |
1698 | return err; | 1778 | return err; |
1699 | 1779 | ||
1700 | down_write(&namespace_sem); | 1780 | err = lock_mount(path); |
1781 | if (err) | ||
1782 | goto out; | ||
1783 | |||
1701 | err = -EINVAL; | 1784 | err = -EINVAL; |
1702 | if (IS_MNT_UNBINDABLE(old_path.mnt)) | 1785 | if (IS_MNT_UNBINDABLE(old_path.mnt)) |
1703 | goto out; | 1786 | goto out2; |
1704 | 1787 | ||
1705 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) | 1788 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) |
1706 | goto out; | 1789 | goto out2; |
1707 | 1790 | ||
1708 | err = -ENOMEM; | 1791 | err = -ENOMEM; |
1709 | if (recurse) | 1792 | if (recurse) |
@@ -1712,20 +1795,18 @@ static int do_loopback(struct path *path, char *old_name, | |||
1712 | mnt = clone_mnt(old_path.mnt, old_path.dentry, 0); | 1795 | mnt = clone_mnt(old_path.mnt, old_path.dentry, 0); |
1713 | 1796 | ||
1714 | if (!mnt) | 1797 | if (!mnt) |
1715 | goto out; | 1798 | goto out2; |
1716 | 1799 | ||
1717 | err = graft_tree(mnt, path); | 1800 | err = graft_tree(mnt, path); |
1718 | if (err) { | 1801 | if (err) { |
1719 | LIST_HEAD(umount_list); | ||
1720 | |||
1721 | br_write_lock(vfsmount_lock); | 1802 | br_write_lock(vfsmount_lock); |
1722 | umount_tree(mnt, 0, &umount_list); | 1803 | umount_tree(mnt, 0, &umount_list); |
1723 | br_write_unlock(vfsmount_lock); | 1804 | br_write_unlock(vfsmount_lock); |
1724 | release_mounts(&umount_list); | ||
1725 | } | 1805 | } |
1726 | 1806 | out2: | |
1807 | unlock_mount(path); | ||
1808 | release_mounts(&umount_list); | ||
1727 | out: | 1809 | out: |
1728 | up_write(&namespace_sem); | ||
1729 | path_put(&old_path); | 1810 | path_put(&old_path); |
1730 | return err; | 1811 | return err; |
1731 | } | 1812 | } |
@@ -1767,6 +1848,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
1767 | if (path->dentry != path->mnt->mnt_root) | 1848 | if (path->dentry != path->mnt->mnt_root) |
1768 | return -EINVAL; | 1849 | return -EINVAL; |
1769 | 1850 | ||
1851 | err = security_sb_remount(sb, data); | ||
1852 | if (err) | ||
1853 | return err; | ||
1854 | |||
1770 | down_write(&sb->s_umount); | 1855 | down_write(&sb->s_umount); |
1771 | if (flags & MS_BIND) | 1856 | if (flags & MS_BIND) |
1772 | err = change_mount_flags(path->mnt, flags); | 1857 | err = change_mount_flags(path->mnt, flags); |
@@ -1810,18 +1895,12 @@ static int do_move_mount(struct path *path, char *old_name) | |||
1810 | if (err) | 1895 | if (err) |
1811 | return err; | 1896 | return err; |
1812 | 1897 | ||
1813 | down_write(&namespace_sem); | 1898 | err = lock_mount(path); |
1814 | err = follow_down(path, true); | ||
1815 | if (err < 0) | 1899 | if (err < 0) |
1816 | goto out; | 1900 | goto out; |
1817 | 1901 | ||
1818 | err = -EINVAL; | 1902 | err = -EINVAL; |
1819 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) | 1903 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) |
1820 | goto out; | ||
1821 | |||
1822 | err = -ENOENT; | ||
1823 | mutex_lock(&path->dentry->d_inode->i_mutex); | ||
1824 | if (cant_mount(path->dentry)) | ||
1825 | goto out1; | 1904 | goto out1; |
1826 | 1905 | ||
1827 | if (d_unlinked(path->dentry)) | 1906 | if (d_unlinked(path->dentry)) |
@@ -1863,16 +1942,87 @@ static int do_move_mount(struct path *path, char *old_name) | |||
1863 | * automatically */ | 1942 | * automatically */ |
1864 | list_del_init(&old_path.mnt->mnt_expire); | 1943 | list_del_init(&old_path.mnt->mnt_expire); |
1865 | out1: | 1944 | out1: |
1866 | mutex_unlock(&path->dentry->d_inode->i_mutex); | 1945 | unlock_mount(path); |
1867 | out: | 1946 | out: |
1868 | up_write(&namespace_sem); | ||
1869 | if (!err) | 1947 | if (!err) |
1870 | path_put(&parent_path); | 1948 | path_put(&parent_path); |
1871 | path_put(&old_path); | 1949 | path_put(&old_path); |
1872 | return err; | 1950 | return err; |
1873 | } | 1951 | } |
1874 | 1952 | ||
1875 | static int do_add_mount(struct vfsmount *, struct path *, int); | 1953 | static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) |
1954 | { | ||
1955 | int err; | ||
1956 | const char *subtype = strchr(fstype, '.'); | ||
1957 | if (subtype) { | ||
1958 | subtype++; | ||
1959 | err = -EINVAL; | ||
1960 | if (!subtype[0]) | ||
1961 | goto err; | ||
1962 | } else | ||
1963 | subtype = ""; | ||
1964 | |||
1965 | mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL); | ||
1966 | err = -ENOMEM; | ||
1967 | if (!mnt->mnt_sb->s_subtype) | ||
1968 | goto err; | ||
1969 | return mnt; | ||
1970 | |||
1971 | err: | ||
1972 | mntput(mnt); | ||
1973 | return ERR_PTR(err); | ||
1974 | } | ||
1975 | |||
1976 | struct vfsmount * | ||
1977 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) | ||
1978 | { | ||
1979 | struct file_system_type *type = get_fs_type(fstype); | ||
1980 | struct vfsmount *mnt; | ||
1981 | if (!type) | ||
1982 | return ERR_PTR(-ENODEV); | ||
1983 | mnt = vfs_kern_mount(type, flags, name, data); | ||
1984 | if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) && | ||
1985 | !mnt->mnt_sb->s_subtype) | ||
1986 | mnt = fs_set_subtype(mnt, fstype); | ||
1987 | put_filesystem(type); | ||
1988 | return mnt; | ||
1989 | } | ||
1990 | EXPORT_SYMBOL_GPL(do_kern_mount); | ||
1991 | |||
1992 | /* | ||
1993 | * add a mount into a namespace's mount tree | ||
1994 | */ | ||
1995 | static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) | ||
1996 | { | ||
1997 | int err; | ||
1998 | |||
1999 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL); | ||
2000 | |||
2001 | err = lock_mount(path); | ||
2002 | if (err) | ||
2003 | return err; | ||
2004 | |||
2005 | err = -EINVAL; | ||
2006 | if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt)) | ||
2007 | goto unlock; | ||
2008 | |||
2009 | /* Refuse the same filesystem on the same mount point */ | ||
2010 | err = -EBUSY; | ||
2011 | if (path->mnt->mnt_sb == newmnt->mnt_sb && | ||
2012 | path->mnt->mnt_root == path->dentry) | ||
2013 | goto unlock; | ||
2014 | |||
2015 | err = -EINVAL; | ||
2016 | if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) | ||
2017 | goto unlock; | ||
2018 | |||
2019 | newmnt->mnt_flags = mnt_flags; | ||
2020 | err = graft_tree(newmnt, path); | ||
2021 | |||
2022 | unlock: | ||
2023 | unlock_mount(path); | ||
2024 | return err; | ||
2025 | } | ||
1876 | 2026 | ||
1877 | /* | 2027 | /* |
1878 | * create a new mount for userspace and request it to be added into the | 2028 | * create a new mount for userspace and request it to be added into the |
@@ -1932,43 +2082,6 @@ fail: | |||
1932 | return err; | 2082 | return err; |
1933 | } | 2083 | } |
1934 | 2084 | ||
1935 | /* | ||
1936 | * add a mount into a namespace's mount tree | ||
1937 | */ | ||
1938 | static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) | ||
1939 | { | ||
1940 | int err; | ||
1941 | |||
1942 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL); | ||
1943 | |||
1944 | down_write(&namespace_sem); | ||
1945 | /* Something was mounted here while we slept */ | ||
1946 | err = follow_down(path, true); | ||
1947 | if (err < 0) | ||
1948 | goto unlock; | ||
1949 | |||
1950 | err = -EINVAL; | ||
1951 | if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt)) | ||
1952 | goto unlock; | ||
1953 | |||
1954 | /* Refuse the same filesystem on the same mount point */ | ||
1955 | err = -EBUSY; | ||
1956 | if (path->mnt->mnt_sb == newmnt->mnt_sb && | ||
1957 | path->mnt->mnt_root == path->dentry) | ||
1958 | goto unlock; | ||
1959 | |||
1960 | err = -EINVAL; | ||
1961 | if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) | ||
1962 | goto unlock; | ||
1963 | |||
1964 | newmnt->mnt_flags = mnt_flags; | ||
1965 | err = graft_tree(newmnt, path); | ||
1966 | |||
1967 | unlock: | ||
1968 | up_write(&namespace_sem); | ||
1969 | return err; | ||
1970 | } | ||
1971 | |||
1972 | /** | 2085 | /** |
1973 | * mnt_set_expiry - Put a mount on an expiration list | 2086 | * mnt_set_expiry - Put a mount on an expiration list |
1974 | * @mnt: The mount to list. | 2087 | * @mnt: The mount to list. |
@@ -2469,65 +2582,60 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
2469 | error = user_path_dir(new_root, &new); | 2582 | error = user_path_dir(new_root, &new); |
2470 | if (error) | 2583 | if (error) |
2471 | goto out0; | 2584 | goto out0; |
2472 | error = -EINVAL; | ||
2473 | if (!check_mnt(new.mnt)) | ||
2474 | goto out1; | ||
2475 | 2585 | ||
2476 | error = user_path_dir(put_old, &old); | 2586 | error = user_path_dir(put_old, &old); |
2477 | if (error) | 2587 | if (error) |
2478 | goto out1; | 2588 | goto out1; |
2479 | 2589 | ||
2480 | error = security_sb_pivotroot(&old, &new); | 2590 | error = security_sb_pivotroot(&old, &new); |
2481 | if (error) { | 2591 | if (error) |
2482 | path_put(&old); | 2592 | goto out2; |
2483 | goto out1; | ||
2484 | } | ||
2485 | 2593 | ||
2486 | get_fs_root(current->fs, &root); | 2594 | get_fs_root(current->fs, &root); |
2487 | down_write(&namespace_sem); | 2595 | error = lock_mount(&old); |
2488 | mutex_lock(&old.dentry->d_inode->i_mutex); | 2596 | if (error) |
2597 | goto out3; | ||
2598 | |||
2489 | error = -EINVAL; | 2599 | error = -EINVAL; |
2490 | if (IS_MNT_SHARED(old.mnt) || | 2600 | if (IS_MNT_SHARED(old.mnt) || |
2491 | IS_MNT_SHARED(new.mnt->mnt_parent) || | 2601 | IS_MNT_SHARED(new.mnt->mnt_parent) || |
2492 | IS_MNT_SHARED(root.mnt->mnt_parent)) | 2602 | IS_MNT_SHARED(root.mnt->mnt_parent)) |
2493 | goto out2; | 2603 | goto out4; |
2494 | if (!check_mnt(root.mnt)) | 2604 | if (!check_mnt(root.mnt) || !check_mnt(new.mnt)) |
2495 | goto out2; | 2605 | goto out4; |
2496 | error = -ENOENT; | 2606 | error = -ENOENT; |
2497 | if (cant_mount(old.dentry)) | ||
2498 | goto out2; | ||
2499 | if (d_unlinked(new.dentry)) | 2607 | if (d_unlinked(new.dentry)) |
2500 | goto out2; | 2608 | goto out4; |
2501 | if (d_unlinked(old.dentry)) | 2609 | if (d_unlinked(old.dentry)) |
2502 | goto out2; | 2610 | goto out4; |
2503 | error = -EBUSY; | 2611 | error = -EBUSY; |
2504 | if (new.mnt == root.mnt || | 2612 | if (new.mnt == root.mnt || |
2505 | old.mnt == root.mnt) | 2613 | old.mnt == root.mnt) |
2506 | goto out2; /* loop, on the same file system */ | 2614 | goto out4; /* loop, on the same file system */ |
2507 | error = -EINVAL; | 2615 | error = -EINVAL; |
2508 | if (root.mnt->mnt_root != root.dentry) | 2616 | if (root.mnt->mnt_root != root.dentry) |
2509 | goto out2; /* not a mountpoint */ | 2617 | goto out4; /* not a mountpoint */ |
2510 | if (root.mnt->mnt_parent == root.mnt) | 2618 | if (root.mnt->mnt_parent == root.mnt) |
2511 | goto out2; /* not attached */ | 2619 | goto out4; /* not attached */ |
2512 | if (new.mnt->mnt_root != new.dentry) | 2620 | if (new.mnt->mnt_root != new.dentry) |
2513 | goto out2; /* not a mountpoint */ | 2621 | goto out4; /* not a mountpoint */ |
2514 | if (new.mnt->mnt_parent == new.mnt) | 2622 | if (new.mnt->mnt_parent == new.mnt) |
2515 | goto out2; /* not attached */ | 2623 | goto out4; /* not attached */ |
2516 | /* make sure we can reach put_old from new_root */ | 2624 | /* make sure we can reach put_old from new_root */ |
2517 | tmp = old.mnt; | 2625 | tmp = old.mnt; |
2518 | br_write_lock(vfsmount_lock); | ||
2519 | if (tmp != new.mnt) { | 2626 | if (tmp != new.mnt) { |
2520 | for (;;) { | 2627 | for (;;) { |
2521 | if (tmp->mnt_parent == tmp) | 2628 | if (tmp->mnt_parent == tmp) |
2522 | goto out3; /* already mounted on put_old */ | 2629 | goto out4; /* already mounted on put_old */ |
2523 | if (tmp->mnt_parent == new.mnt) | 2630 | if (tmp->mnt_parent == new.mnt) |
2524 | break; | 2631 | break; |
2525 | tmp = tmp->mnt_parent; | 2632 | tmp = tmp->mnt_parent; |
2526 | } | 2633 | } |
2527 | if (!is_subdir(tmp->mnt_mountpoint, new.dentry)) | 2634 | if (!is_subdir(tmp->mnt_mountpoint, new.dentry)) |
2528 | goto out3; | 2635 | goto out4; |
2529 | } else if (!is_subdir(old.dentry, new.dentry)) | 2636 | } else if (!is_subdir(old.dentry, new.dentry)) |
2530 | goto out3; | 2637 | goto out4; |
2638 | br_write_lock(vfsmount_lock); | ||
2531 | detach_mnt(new.mnt, &parent_path); | 2639 | detach_mnt(new.mnt, &parent_path); |
2532 | detach_mnt(root.mnt, &root_parent); | 2640 | detach_mnt(root.mnt, &root_parent); |
2533 | /* mount old root on put_old */ | 2641 | /* mount old root on put_old */ |
@@ -2537,22 +2645,21 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
2537 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 2645 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
2538 | br_write_unlock(vfsmount_lock); | 2646 | br_write_unlock(vfsmount_lock); |
2539 | chroot_fs_refs(&root, &new); | 2647 | chroot_fs_refs(&root, &new); |
2540 | |||
2541 | error = 0; | 2648 | error = 0; |
2542 | path_put(&root_parent); | 2649 | out4: |
2543 | path_put(&parent_path); | 2650 | unlock_mount(&old); |
2544 | out2: | 2651 | if (!error) { |
2545 | mutex_unlock(&old.dentry->d_inode->i_mutex); | 2652 | path_put(&root_parent); |
2546 | up_write(&namespace_sem); | 2653 | path_put(&parent_path); |
2654 | } | ||
2655 | out3: | ||
2547 | path_put(&root); | 2656 | path_put(&root); |
2657 | out2: | ||
2548 | path_put(&old); | 2658 | path_put(&old); |
2549 | out1: | 2659 | out1: |
2550 | path_put(&new); | 2660 | path_put(&new); |
2551 | out0: | 2661 | out0: |
2552 | return error; | 2662 | return error; |
2553 | out3: | ||
2554 | br_write_unlock(vfsmount_lock); | ||
2555 | goto out2; | ||
2556 | } | 2663 | } |
2557 | 2664 | ||
2558 | static void __init init_mount_tree(void) | 2665 | static void __init init_mount_tree(void) |
@@ -2594,7 +2701,7 @@ void __init mnt_init(void) | |||
2594 | if (!mount_hashtable) | 2701 | if (!mount_hashtable) |
2595 | panic("Failed to allocate mount hash table\n"); | 2702 | panic("Failed to allocate mount hash table\n"); |
2596 | 2703 | ||
2597 | printk("Mount-cache hash table entries: %lu\n", HASH_SIZE); | 2704 | printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE); |
2598 | 2705 | ||
2599 | for (u = 0; u < HASH_SIZE; u++) | 2706 | for (u = 0; u < HASH_SIZE; u++) |
2600 | INIT_LIST_HEAD(&mount_hashtable[u]); | 2707 | INIT_LIST_HEAD(&mount_hashtable[u]); |
@@ -2627,3 +2734,9 @@ void put_mnt_ns(struct mnt_namespace *ns) | |||
2627 | kfree(ns); | 2734 | kfree(ns); |
2628 | } | 2735 | } |
2629 | EXPORT_SYMBOL(put_mnt_ns); | 2736 | EXPORT_SYMBOL(put_mnt_ns); |
2737 | |||
2738 | struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) | ||
2739 | { | ||
2740 | return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data); | ||
2741 | } | ||
2742 | EXPORT_SYMBOL_GPL(kern_mount_data); | ||