| @@ -70,6 +70,8 @@ static struct hlist_head *mount_hashtable __read_mostly; · 69 unmodified lines |
| 70 | static struct hlist_head *mountpoint_hashtable __read_mostly; | 70 | static struct hlist_head *mountpoint_hashtable __read_mostly; |
| 71 | static struct kmem_cache *mnt_cache __read_mostly; | 71 | static struct kmem_cache *mnt_cache __read_mostly; |
| 72 | static DECLARE_RWSEM(namespace_sem); | 72 | static DECLARE_RWSEM(namespace_sem); |
| | 73 | static HLIST_HEAD(unmounted); /* protected by namespace_sem */ |
| | 74 | static LIST_HEAD(ex_mountpoints); /* protected by namespace_sem */ |
| 73 | | 75 | |
| 74 | /* /sys/fs */ | 76 | /* /sys/fs */ |
| 75 | struct kobject *fs_kobj; | 77 | struct kobject *fs_kobj; |
| @@ -170,14 +172,6 @@ unsigned int mnt_get_count(struct mount *mnt) · 94 unmodified lines |
| 170 | #endif | 172 | #endif |
| 171 | } | 173 | } |
| 172 | | 174 | |
| 173 | static void drop_mountpoint(struct fs_pin *p) | | |
| 174 | { | | |
| 175 | struct mount *m = container_of(p, struct mount, mnt_umount); | | |
| 176 | dput(m->mnt_ex_mountpoint); | | |
| 177 | pin_remove(p); | | |
| 178 | mntput(&m->mnt); | | |
| 179 | } | | |
| 180 | | | |
| 181 | static struct mount *alloc_vfsmnt(const char *name) | 175 | static struct mount *alloc_vfsmnt(const char *name) |
| 182 | { | 176 | { |
| 183 | struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); | 177 | struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); |
| @@ -215,7 +209,7 @@ static struct mount *alloc_vfsmnt(const char *name) · 31 unmodified lines |
| 215 | INIT_LIST_HEAD(&mnt->mnt_slave); | 209 | INIT_LIST_HEAD(&mnt->mnt_slave); |
| 216 | INIT_HLIST_NODE(&mnt->mnt_mp_list); | 210 | INIT_HLIST_NODE(&mnt->mnt_mp_list); |
| 217 | INIT_LIST_HEAD(&mnt->mnt_umounting); | 211 | INIT_LIST_HEAD(&mnt->mnt_umounting); |
| 218 | init_fs_pin(&mnt->mnt_umount, drop_mountpoint); | 212 | INIT_HLIST_HEAD(&mnt->mnt_stuck_children); |
| 219 | } | 213 | } |
| 220 | return mnt; | 214 | return mnt; |
| 221 | | 215 | |
| @@ -740,7 +734,7 @@ mountpoint: · 518 unmodified lines |
| 740 | | 734 | |
| 741 | /* Add the new mountpoint to the hash table */ | 735 | /* Add the new mountpoint to the hash table */ |
| 742 | read_seqlock_excl(&mount_lock); | 736 | read_seqlock_excl(&mount_lock); |
| 743 | new->m_dentry = dentry; | 737 | new->m_dentry = dget(dentry); |
| 744 | new->m_count = 1; | 738 | new->m_count = 1; |
| 745 | hlist_add_head(&new->m_hash, mp_hash(dentry)); | 739 | hlist_add_head(&new->m_hash, mp_hash(dentry)); |
| 746 | INIT_HLIST_HEAD(&new->m_list); | 740 | INIT_HLIST_HEAD(&new->m_list); |
| @@ -753,7 +747,11 @@ done: · 6 unmodified lines |
| 753 | return mp; | 747 | return mp; |
| 754 | } | 748 | } |
| 755 | | 749 | |
| 756 | static void put_mountpoint(struct mountpoint *mp) | 750 | /* |
| | 751 | * vfsmount lock must be held. Additionally, the caller is responsible |
| | 752 | * for serializing calls for given disposal list. |
| | 753 | */ |
| | 754 | static void __put_mountpoint(struct mountpoint *mp, struct list_head *list) |
| 757 | { | 755 | { |
| 758 | if (!--mp->m_count) { | 756 | if (!--mp->m_count) { |
| 759 | struct dentry *dentry = mp->m_dentry; | 757 | struct dentry *dentry = mp->m_dentry; |
| @@ -761,11 +759,18 @@ static void put_mountpoint(struct mountpoint *mp) · 1 unmodified line |
| 761 | spin_lock(&dentry->d_lock); | 759 | spin_lock(&dentry->d_lock); |
| 762 | dentry->d_flags &= ~DCACHE_MOUNTED; | 760 | dentry->d_flags &= ~DCACHE_MOUNTED; |
| 763 | spin_unlock(&dentry->d_lock); | 761 | spin_unlock(&dentry->d_lock); |
| | 762 | dput_to_list(dentry, list); |
| 764 | hlist_del(&mp->m_hash); | 763 | hlist_del(&mp->m_hash); |
| 765 | kfree(mp); | 764 | kfree(mp); |
| 766 | } | 765 | } |
| 767 | } | 766 | } |
| 768 | | 767 | |
| | 768 | /* called with namespace_lock and vfsmount lock */ |
| | 769 | static void put_mountpoint(struct mountpoint *mp) |
| | 770 | { |
| | 771 | __put_mountpoint(mp, &ex_mountpoints); |
| | 772 | } |
| | 773 | |
| 769 | static inline int check_mnt(struct mount *mnt) | 774 | static inline int check_mnt(struct mount *mnt) |
| 770 | { | 775 | { |
| 771 | return mnt->mnt_ns == current->nsproxy->mnt_ns; | 776 | return mnt->mnt_ns == current->nsproxy->mnt_ns; |
| @@ -796,25 +801,17 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) · 24 unmodified lines |
| 796 | /* | 801 | /* |
| 797 | * vfsmount lock must be held for write | 802 | * vfsmount lock must be held for write |
| 798 | */ | 803 | */ |
| 799 | static void unhash_mnt(struct mount *mnt) | 804 | static struct mountpoint *unhash_mnt(struct mount *mnt) |
| 800 | { | 805 | { |
| | 806 | struct mountpoint *mp; |
| 801 | mnt->mnt_parent = mnt; | 807 | mnt->mnt_parent = mnt; |
| 802 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; | 808 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; |
| 803 | list_del_init(&mnt->mnt_child); | 809 | list_del_init(&mnt->mnt_child); |
| 804 | hlist_del_init_rcu(&mnt->mnt_hash); | 810 | hlist_del_init_rcu(&mnt->mnt_hash); |
| 805 | hlist_del_init(&mnt->mnt_mp_list); | 811 | hlist_del_init(&mnt->mnt_mp_list); |
| 806 | put_mountpoint(mnt->mnt_mp); | 812 | mp = mnt->mnt_mp; |
| 807 | mnt->mnt_mp = NULL; | 813 | mnt->mnt_mp = NULL; |
| 808 | } | 814 | return mp; |
| 809 | | | |
| 810 | /* | | |
| 811 | * vfsmount lock must be held for write | | |
| 812 | */ | | |
| 813 | static void detach_mnt(struct mount *mnt, struct path *old_path) | | |
| 814 | { | | |
| 815 | old_path->dentry = mnt->mnt_mountpoint; | | |
| 816 | old_path->mnt = &mnt->mnt_parent->mnt; | | |
| 817 | unhash_mnt(mnt); | | |
| 818 | } | 815 | } |
| 819 | | 816 | |
| 820 | /* | 817 | /* |
| @@ -822,9 +819,7 @@ static void detach_mnt(struct mount *mnt, struct path *old_path) · 1 unmodified line |
| 822 | */ | 819 | */ |
| 823 | static void umount_mnt(struct mount *mnt) | 820 | static void umount_mnt(struct mount *mnt) |
| 824 | { | 821 | { |
| 825 | /* old mountpoint will be dropped when we can do that */ | 822 | put_mountpoint(unhash_mnt(mnt)); |
| 826 | mnt->mnt_ex_mountpoint = mnt->mnt_mountpoint; | | |
| 827 | unhash_mnt(mnt); | | |
| 828 | } | 823 | } |
| 829 | | 824 | |
| 830 | /* | 825 | /* |
| @@ -836,7 +831,7 @@ void mnt_set_mountpoint(struct mount *mnt, · 5 unmodified lines |
| 836 | { | 831 | { |
| 837 | mp->m_count++; | 832 | mp->m_count++; |
| 838 | mnt_add_count(mnt, 1); /* essentially, that's mntget */ | 833 | mnt_add_count(mnt, 1); /* essentially, that's mntget */ |
| 839 | child_mnt->mnt_mountpoint = dget(mp->m_dentry); | 834 | child_mnt->mnt_mountpoint = mp->m_dentry; |
| 840 | child_mnt->mnt_parent = mnt; | 835 | child_mnt->mnt_parent = mnt; |
| 841 | child_mnt->mnt_mp = mp; | 836 | child_mnt->mnt_mp = mp; |
| 842 | hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list); | 837 | hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list); |
| @@ -863,7 +858,6 @@ static void attach_mnt(struct mount *mnt, · 20 unmodified lines |
| 863 | void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct mount *mnt) | 858 | void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct mount *mnt) |
| 864 | { | 859 | { |
| 865 | struct mountpoint *old_mp = mnt->mnt_mp; | 860 | struct mountpoint *old_mp = mnt->mnt_mp; |
| 866 | struct dentry *old_mountpoint = mnt->mnt_mountpoint; | | |
| 867 | struct mount *old_parent = mnt->mnt_parent; | 861 | struct mount *old_parent = mnt->mnt_parent; |
| 868 | | 862 | |
| 869 | list_del_init(&mnt->mnt_child); | 863 | list_del_init(&mnt->mnt_child); |
| @@ -873,22 +867,6 @@ void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct m · 3 unmodified lines |
| 873 | attach_mnt(mnt, parent, mp); | 867 | attach_mnt(mnt, parent, mp); |
| 874 | | 868 | |
| 875 | put_mountpoint(old_mp); | 869 | put_mountpoint(old_mp); |
| 876 | | | |
| 877 | /* | | |
| 878 | * Safely avoid even the suggestion this code might sleep or | | |
| 879 | * lock the mount hash by taking advantage of the knowledge that | | |
| 880 | * mnt_change_mountpoint will not release the final reference | | |
| 881 | * to a mountpoint. | | |
| 882 | * | | |
| 883 | * During mounting, the mount passed in as the parent mount will | | |
| 884 | * continue to use the old mountpoint and during unmounting, the | | |
| 885 | * old mountpoint will continue to exist until namespace_unlock, | | |
| 886 | * which happens well after mnt_change_mountpoint. | | |
| 887 | */ | | |
| 888 | spin_lock(&old_mountpoint->d_lock); | | |
| 889 | old_mountpoint->d_lockref.count--; | | |
| 890 | spin_unlock(&old_mountpoint->d_lock); | | |
| 891 | | | |
| 892 | mnt_add_count(old_parent, -1); | 870 | mnt_add_count(old_parent, -1); |
| 893 | } | 871 | } |
| 894 | | 872 | |
| @@ -1103,19 +1081,22 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, · 208 unmodified lines |
| 1103 | | 1081 | |
| 1104 | static void cleanup_mnt(struct mount *mnt) | 1082 | static void cleanup_mnt(struct mount *mnt) |
| 1105 | { | 1083 | { |
| | 1084 | struct hlist_node *p; |
| | 1085 | struct mount *m; |
| 1106 | /* | 1086 | /* |
| 1107 | * This probably indicates that somebody messed | 1087 | * The warning here probably indicates that somebody messed |
| 1108 | * up a mnt_want/drop_write() pair. If this | 1088 | * up a mnt_want/drop_write() pair. If this happens, the |
| 1109 | * happens, the filesystem was probably unable | 1089 | * filesystem was probably unable to make r/w->r/o transitions. |
| 1110 | * to make r/w->r/o transitions. | | |
| 1111 | */ | | |
| 1112 | /* | | |
| 1113 | * The locking used to deal with mnt_count decrement provides barriers, | 1090 | * The locking used to deal with mnt_count decrement provides barriers, |
| 1114 | * so mnt_get_writers() below is safe. | 1091 | * so mnt_get_writers() below is safe. |
| 1115 | */ | 1092 | */ |
| 1116 | WARN_ON(mnt_get_writers(mnt)); | 1093 | WARN_ON(mnt_get_writers(mnt)); |
| 1117 | if (unlikely(mnt->mnt_pins.first)) | 1094 | if (unlikely(mnt->mnt_pins.first)) |
| 1118 | mnt_pin_kill(mnt); | 1095 | mnt_pin_kill(mnt); |
| | 1096 | hlist_for_each_entry_safe(m, p, &mnt->mnt_stuck_children, mnt_umount) { |
| | 1097 | hlist_del(&m->mnt_umount); |
| | 1098 | mntput(&m->mnt); |
| | 1099 | } |
| 1119 | fsnotify_vfsmount_delete(&mnt->mnt); | 1100 | fsnotify_vfsmount_delete(&mnt->mnt); |
| 1120 | dput(mnt->mnt.mnt_root); | 1101 | dput(mnt->mnt.mnt_root); |
| 1121 | deactivate_super(mnt->mnt.mnt_sb); | 1102 | deactivate_super(mnt->mnt.mnt_sb); |
| @@ -1141,6 +1122,8 @@ static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput); · 19 unmodified lines |
| 1141 | | 1122 | |
| 1142 | static void mntput_no_expire(struct mount *mnt) | 1123 | static void mntput_no_expire(struct mount *mnt) |
| 1143 | { | 1124 | { |
| | 1125 | LIST_HEAD(list); |
| | 1126 | |
| 1144 | rcu_read_lock(); | 1127 | rcu_read_lock(); |
| 1145 | if (likely(READ_ONCE(mnt->mnt_ns))) { | 1128 | if (likely(READ_ONCE(mnt->mnt_ns))) { |
| 1146 | /* | 1129 | /* |
| @@ -1181,10 +1164,12 @@ static void mntput_no_expire(struct mount *mnt) · 34 unmodified lines |
| 1181 | if (unlikely(!list_empty(&mnt->mnt_mounts))) { | 1164 | if (unlikely(!list_empty(&mnt->mnt_mounts))) { |
| 1182 | struct mount *p, *tmp; | 1165 | struct mount *p, *tmp; |
| 1183 | list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) { | 1166 | list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) { |
| 1184 | umount_mnt(p); | 1167 | __put_mountpoint(unhash_mnt(p), &list); |
| | 1168 | hlist_add_head(&p->mnt_umount, &mnt->mnt_stuck_children); |
| 1185 | } | 1169 | } |
| 1186 | } | 1170 | } |
| 1187 | unlock_mount_hash(); | 1171 | unlock_mount_hash(); |
| | 1172 | shrink_dentry_list(&list); |
| 1188 | | 1173 | |
| 1189 | if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) { | 1174 | if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) { |
| 1190 | struct task_struct *task = current; | 1175 | struct task_struct *task = current; |
| @@ -1370,22 +1355,29 @@ int may_umount(struct vfsmount *mnt) · 179 unmodified lines |
| 1370 | | 1355 | |
| 1371 | EXPORT_SYMBOL(may_umount); | 1356 | EXPORT_SYMBOL(may_umount); |
| 1372 | | 1357 | |
| 1373 | static HLIST_HEAD(unmounted); /* protected by namespace_sem */ | | |
| 1374 | | | |
| 1375 | static void namespace_unlock(void) | 1358 | static void namespace_unlock(void) |
| 1376 | { | 1359 | { |
| 1377 | struct hlist_head head; | 1360 | struct hlist_head head; |
| | 1361 | struct hlist_node *p; |
| | 1362 | struct mount *m; |
| | 1363 | LIST_HEAD(list); |
| 1378 | | 1364 | |
| 1379 | hlist_move_list(&unmounted, &head); | 1365 | hlist_move_list(&unmounted, &head); |
| | 1366 | list_splice_init(&ex_mountpoints, &list); |
| 1380 | | 1367 | |
| 1381 | up_write(&namespace_sem); | 1368 | up_write(&namespace_sem); |
| 1382 | | 1369 | |
| | 1370 | shrink_dentry_list(&list); |
| | 1371 | |
| 1383 | if (likely(hlist_empty(&head))) | 1372 | if (likely(hlist_empty(&head))) |
| 1384 | return; | 1373 | return; |
| 1385 | | 1374 | |
| 1386 | synchronize_rcu_expedited(); | 1375 | synchronize_rcu_expedited(); |
| 1387 | | 1376 | |
| 1388 | group_pin_kill(&head); | 1377 | hlist_for_each_entry_safe(m, p, &head, mnt_umount) { |
| | 1378 | hlist_del(&m->mnt_umount); |
| | 1379 | mntput(&m->mnt); |
| | 1380 | } |
| 1389 | } | 1381 | } |
| 1390 | | 1382 | |
| 1391 | static inline void namespace_lock(void) | 1383 | static inline void namespace_lock(void) |
| @@ -1472,8 +1464,6 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) · 80 unmodified lines |
| 1472 | | 1464 | |
| 1473 | disconnect = disconnect_mount(p, how); | 1465 | disconnect = disconnect_mount(p, how); |
| 1474 | | 1466 | |
| 1475 | pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, | | |
| 1476 | disconnect ? &unmounted : NULL); | | |
| 1477 | if (mnt_has_parent(p)) { | 1467 | if (mnt_has_parent(p)) { |
| 1478 | mnt_add_count(p->mnt_parent, -1); | 1468 | mnt_add_count(p->mnt_parent, -1); |
| 1479 | if (!disconnect) { | 1469 | if (!disconnect) { |
| @@ -1481,6 +1471,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) · 1 unmodified line |
| 1481 | list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts); | 1471 | list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts); |
| 1482 | } else { | 1472 | } else { |
| 1483 | umount_mnt(p); | 1473 | umount_mnt(p); |
| | 1474 | hlist_add_head(&p->mnt_umount, &unmounted); |
| 1484 | } | 1475 | } |
| 1485 | } | 1476 | } |
| 1486 | change_mnt_propagation(p, MS_PRIVATE); | 1477 | change_mnt_propagation(p, MS_PRIVATE); |
| @@ -1626,15 +1617,15 @@ void __detach_mounts(struct dentry *dentry) · 139 unmodified lines |
| 1626 | namespace_lock(); | 1617 | namespace_lock(); |
| 1627 | lock_mount_hash(); | 1618 | lock_mount_hash(); |
| 1628 | mp = lookup_mountpoint(dentry); | 1619 | mp = lookup_mountpoint(dentry); |
| 1629 | if (IS_ERR_OR_NULL(mp)) | 1620 | if (!mp) |
| 1630 | goto out_unlock; | 1621 | goto out_unlock; |
| 1631 | | 1622 | |
| 1632 | event++; | 1623 | event++; |
| 1633 | while (!hlist_empty(&mp->m_list)) { | 1624 | while (!hlist_empty(&mp->m_list)) { |
| 1634 | mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); | 1625 | mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); |
| 1635 | if (mnt->mnt.mnt_flags & MNT_UMOUNT) { | 1626 | if (mnt->mnt.mnt_flags & MNT_UMOUNT) { |
| 1636 | hlist_add_head(&mnt->mnt_umount.s_list, &unmounted); | | |
| 1637 | umount_mnt(mnt); | 1627 | umount_mnt(mnt); |
| | 1628 | hlist_add_head(&mnt->mnt_umount, &unmounted); |
| 1638 | } | 1629 | } |
| 1639 | else umount_tree(mnt, UMOUNT_CONNECTED); | 1630 | else umount_tree(mnt, UMOUNT_CONNECTED); |
| 1640 | } | 1631 | } |
| @@ -2046,7 +2037,7 @@ int count_mounts(struct mnt_namespace *ns, struct mount *mnt) · 405 unmodified lines |
| 2046 | static int attach_recursive_mnt(struct mount *source_mnt, | 2037 | static int attach_recursive_mnt(struct mount *source_mnt, |
| 2047 | struct mount *dest_mnt, | 2038 | struct mount *dest_mnt, |
| 2048 | struct mountpoint *dest_mp, | 2039 | struct mountpoint *dest_mp, |
| 2049 | struct path *parent_path) | 2040 | bool moving) |
| 2050 | { | 2041 | { |
| 2051 | struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; | 2042 | struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; |
| 2052 | HLIST_HEAD(tree_list); | 2043 | HLIST_HEAD(tree_list); |
| @@ -2064,7 +2055,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, · 11 unmodified lines |
| 2064 | return PTR_ERR(smp); | 2055 | return PTR_ERR(smp); |
| 2065 | | 2056 | |
| 2066 | /* Is there space to add these mounts to the mount namespace? */ | 2057 | /* Is there space to add these mounts to the mount namespace? */ |
| 2067 | if (!parent_path) { | 2058 | if (!moving) { |
| 2068 | err = count_mounts(ns, source_mnt); | 2059 | err = count_mounts(ns, source_mnt); |
| 2069 | if (err) | 2060 | if (err) |
| 2070 | goto out; | 2061 | goto out; |
| @@ -2083,8 +2074,8 @@ static int attach_recursive_mnt(struct mount *source_mnt, · 12 unmodified lines |
| 2083 | } else { | 2074 | } else { |
| 2084 | lock_mount_hash(); | 2075 | lock_mount_hash(); |
| 2085 | } | 2076 | } |
| 2086 | if (parent_path) { | 2077 | if (moving) { |
| 2087 | detach_mnt(source_mnt, parent_path); | 2078 | unhash_mnt(source_mnt); |
| 2088 | attach_mnt(source_mnt, dest_mnt, dest_mp); | 2079 | attach_mnt(source_mnt, dest_mnt, dest_mp); |
| 2089 | touch_mnt_namespace(source_mnt->mnt_ns); | 2080 | touch_mnt_namespace(source_mnt->mnt_ns); |
| 2090 | } else { | 2081 | } else { |
| @@ -2182,7 +2173,7 @@ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp) · 91 unmodified lines |
| 2182 | d_is_dir(mnt->mnt.mnt_root)) | 2173 | d_is_dir(mnt->mnt.mnt_root)) |
| 2183 | return -ENOTDIR; | 2174 | return -ENOTDIR; |
| 2184 | | 2175 | |
| 2185 | return attach_recursive_mnt(mnt, p, mp, NULL); | 2176 | return attach_recursive_mnt(mnt, p, mp, false); |
| 2186 | } | 2177 | } |
| 2187 | | 2178 | |
| 2188 | /* | 2179 | /* |
| @@ -2575,11 +2566,11 @@ out: · 386 unmodified lines |
| 2575 | | 2566 | |
| 2576 | static int do_move_mount(struct path *old_path, struct path *new_path) | 2567 | static int do_move_mount(struct path *old_path, struct path *new_path) |
| 2577 | { | 2568 | { |
| 2578 | struct path parent_path = {.mnt = NULL, .dentry = NULL}; | | |
| 2579 | struct mnt_namespace *ns; | 2569 | struct mnt_namespace *ns; |
| 2580 | struct mount *p; | 2570 | struct mount *p; |
| 2581 | struct mount *old; | 2571 | struct mount *old; |
| 2582 | struct mountpoint *mp; | 2572 | struct mount *parent; |
| | 2573 | struct mountpoint *mp, *old_mp; |
| 2583 | int err; | 2574 | int err; |
| 2584 | bool attached; | 2575 | bool attached; |
| 2585 | | 2576 | |
| @@ -2589,7 +2580,9 @@ static int do_move_mount(struct path *old_path, struct path *new_path) · 3 unmodified lines |
| 2589 | | 2580 | |
| 2590 | old = real_mount(old_path->mnt); | 2581 | old = real_mount(old_path->mnt); |
| 2591 | p = real_mount(new_path->mnt); | 2582 | p = real_mount(new_path->mnt); |
| | 2583 | parent = old->mnt_parent; |
| 2592 | attached = mnt_has_parent(old); | 2584 | attached = mnt_has_parent(old); |
| | 2585 | old_mp = old->mnt_mp; |
| 2593 | ns = old->mnt_ns; | 2586 | ns = old->mnt_ns; |
| 2594 | | 2587 | |
| 2595 | err = -EINVAL; | 2588 | err = -EINVAL; |
| @@ -2617,7 +2610,7 @@ static int do_move_mount(struct path *old_path, struct path *new_path) · 21 unmodified lines |
| 2617 | /* | 2610 | /* |
| 2618 | * Don't move a mount residing in a shared parent. | 2611 | * Don't move a mount residing in a shared parent. |
| 2619 | */ | 2612 | */ |
| 2620 | if (attached && IS_MNT_SHARED(old->mnt_parent)) | 2613 | if (attached && IS_MNT_SHARED(parent)) |
| 2621 | goto out; | 2614 | goto out; |
| 2622 | /* | 2615 | /* |
| 2623 | * Don't move a mount tree containing unbindable mounts to a destination | 2616 | * Don't move a mount tree containing unbindable mounts to a destination |
| @@ -2633,18 +2626,21 @@ static int do_move_mount(struct path *old_path, struct path *new_path) · 9 unmodified lines |
| 2633 | goto out; | 2626 | goto out; |
| 2634 | | 2627 | |
| 2635 | err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp, | 2628 | err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp, |
| 2636 | attached ? &parent_path : NULL); | 2629 | attached); |
| 2637 | if (err) | 2630 | if (err) |
| 2638 | goto out; | 2631 | goto out; |
| 2639 | | 2632 | |
| 2640 | /* if the mount is moved, it should no longer be expire | 2633 | /* if the mount is moved, it should no longer be expire |
| 2641 | * automatically */ | 2634 | * automatically */ |
| 2642 | list_del_init(&old->mnt_expire); | 2635 | list_del_init(&old->mnt_expire); |
| | 2636 | if (attached) |
| | 2637 | put_mountpoint(old_mp); |
| 2643 | out: | 2638 | out: |
| 2644 | unlock_mount(mp); | 2639 | unlock_mount(mp); |
| 2645 | if (!err) { | 2640 | if (!err) { |
| 2646 | path_put(&parent_path); | 2641 | if (attached) |
| 2647 | if (!attached) | 2642 | mntput_no_expire(parent); |
| | 2643 | else |
| 2648 | free_mnt_ns(ns); | 2644 | free_mnt_ns(ns); |
| 2649 | } | 2645 | } |
| 2650 | return err; | 2646 | return err; |
| @@ -3589,8 +3585,8 @@ EXPORT_SYMBOL(path_is_under); · 938 unmodified lines |
| 3589 | SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | 3585 | SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, |
| 3590 | const char __user *, put_old) | 3586 | const char __user *, put_old) |
| 3591 | { | 3587 | { |
| 3592 | struct path new, old, parent_path, root_parent, root; | 3588 | struct path new, old, root; |
| 3593 | struct mount *new_mnt, *root_mnt, *old_mnt; | 3589 | struct mount *new_mnt, *root_mnt, *old_mnt, *root_parent, *ex_parent; |
| 3594 | struct mountpoint *old_mp, *root_mp; | 3590 | struct mountpoint *old_mp, *root_mp; |
| 3595 | int error; | 3591 | int error; |
| 3596 | | 3592 | |
| @@ -3619,9 +3615,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 22 unmodified lines |
| 3619 | new_mnt = real_mount(new.mnt); | 3615 | new_mnt = real_mount(new.mnt); |
| 3620 | root_mnt = real_mount(root.mnt); | 3616 | root_mnt = real_mount(root.mnt); |
| 3621 | old_mnt = real_mount(old.mnt); | 3617 | old_mnt = real_mount(old.mnt); |
| | 3618 | ex_parent = new_mnt->mnt_parent; |
| | 3619 | root_parent = root_mnt->mnt_parent; |
| 3622 | if (IS_MNT_SHARED(old_mnt) || | 3620 | if (IS_MNT_SHARED(old_mnt) || |
| 3623 | IS_MNT_SHARED(new_mnt->mnt_parent) || | 3621 | IS_MNT_SHARED(ex_parent) || |
| 3624 | IS_MNT_SHARED(root_mnt->mnt_parent)) | 3622 | IS_MNT_SHARED(root_parent)) |
| 3625 | goto out4; | 3623 | goto out4; |
| 3626 | if (!check_mnt(root_mnt) || !check_mnt(new_mnt)) | 3624 | if (!check_mnt(root_mnt) || !check_mnt(new_mnt)) |
| 3627 | goto out4; | 3625 | goto out4; |
| @@ -3638,7 +3636,6 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 10 unmodified lines |
| 3638 | goto out4; /* not a mountpoint */ | 3636 | goto out4; /* not a mountpoint */ |
| 3639 | if (!mnt_has_parent(root_mnt)) | 3637 | if (!mnt_has_parent(root_mnt)) |
| 3640 | goto out4; /* not attached */ | 3638 | goto out4; /* not attached */ |
| 3641 | root_mp = root_mnt->mnt_mp; | | |
| 3642 | if (new.mnt->mnt_root != new.dentry) | 3639 | if (new.mnt->mnt_root != new.dentry) |
| 3643 | goto out4; /* not a mountpoint */ | 3640 | goto out4; /* not a mountpoint */ |
| 3644 | if (!mnt_has_parent(new_mnt)) | 3641 | if (!mnt_has_parent(new_mnt)) |
| @@ -3649,10 +3646,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 4 unmodified lines |
| 3649 | /* make certain new is below the root */ | 3646 | /* make certain new is below the root */ |
| 3650 | if (!is_path_reachable(new_mnt, new.dentry, &root)) | 3647 | if (!is_path_reachable(new_mnt, new.dentry, &root)) |
| 3651 | goto out4; | 3648 | goto out4; |
| 3652 | root_mp->m_count++; /* pin it so it won't go away */ | | |
| 3653 | lock_mount_hash(); | 3649 | lock_mount_hash(); |
| 3654 | detach_mnt(new_mnt, &parent_path); | 3650 | umount_mnt(new_mnt); |
| 3655 | detach_mnt(root_mnt, &root_parent); | 3651 | root_mp = unhash_mnt(root_mnt); /* we'll need its mountpoint */ |
| 3656 | if (root_mnt->mnt.mnt_flags & MNT_LOCKED) { | 3652 | if (root_mnt->mnt.mnt_flags & MNT_LOCKED) { |
| 3657 | new_mnt->mnt.mnt_flags |= MNT_LOCKED; | 3653 | new_mnt->mnt.mnt_flags |= MNT_LOCKED; |
| 3658 | root_mnt->mnt.mnt_flags &= ~MNT_LOCKED; | 3654 | root_mnt->mnt.mnt_flags &= ~MNT_LOCKED; |
| @@ -3660,7 +3656,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 1 unmodified line |
| 3660 | /* mount old root on put_old */ | 3656 | /* mount old root on put_old */ |
| 3661 | attach_mnt(root_mnt, old_mnt, old_mp); | 3657 | attach_mnt(root_mnt, old_mnt, old_mp); |
| 3662 | /* mount new_root on / */ | 3658 | /* mount new_root on / */ |
| 3663 | attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp); | 3659 | attach_mnt(new_mnt, root_parent, root_mp); |
| | 3660 | mnt_add_count(root_parent, -1); |
| 3664 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 3661 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
| 3665 | /* A moved mount should not expire automatically */ | 3662 | /* A moved mount should not expire automatically */ |
| 3666 | list_del_init(&new_mnt->mnt_expire); | 3663 | list_del_init(&new_mnt->mnt_expire); |
| @@ -3670,10 +3667,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, · 3 unmodified lines |
| 3670 | error = 0; | 3667 | error = 0; |
| 3671 | out4: | 3668 | out4: |
| 3672 | unlock_mount(old_mp); | 3669 | unlock_mount(old_mp); |
| 3673 | if (!error) { | 3670 | if (!error) |
| 3674 | path_put(&root_parent); | 3671 | mntput_no_expire(ex_parent); |
| 3675 | path_put(&parent_path); | | |
| 3676 | } | | |
| 3677 | out3: | 3672 | out3: |
| 3678 | path_put(&root); | 3673 | path_put(&root); |
| 3679 | out2: | 3674 | out2: |