diff options
Diffstat (limited to 'fs/namespace.c')
| -rw-r--r-- | fs/namespace.c | 72 |
1 files changed, 46 insertions, 26 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index c768f733c8d6..88058de59c7c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -573,7 +573,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | |||
| 573 | mnt->mnt_master = old; | 573 | mnt->mnt_master = old; |
| 574 | CLEAR_MNT_SHARED(mnt); | 574 | CLEAR_MNT_SHARED(mnt); |
| 575 | } else if (!(flag & CL_PRIVATE)) { | 575 | } else if (!(flag & CL_PRIVATE)) { |
| 576 | if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) | 576 | if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old)) |
| 577 | list_add(&mnt->mnt_share, &old->mnt_share); | 577 | list_add(&mnt->mnt_share, &old->mnt_share); |
| 578 | if (IS_MNT_SLAVE(old)) | 578 | if (IS_MNT_SLAVE(old)) |
| 579 | list_add(&mnt->mnt_slave, &old->mnt_slave); | 579 | list_add(&mnt->mnt_slave, &old->mnt_slave); |
| @@ -628,7 +628,6 @@ repeat: | |||
| 628 | mnt->mnt_pinned = 0; | 628 | mnt->mnt_pinned = 0; |
| 629 | spin_unlock(&vfsmount_lock); | 629 | spin_unlock(&vfsmount_lock); |
| 630 | acct_auto_close_mnt(mnt); | 630 | acct_auto_close_mnt(mnt); |
| 631 | security_sb_umount_close(mnt); | ||
| 632 | goto repeat; | 631 | goto repeat; |
| 633 | } | 632 | } |
| 634 | } | 633 | } |
| @@ -737,6 +736,21 @@ static void m_stop(struct seq_file *m, void *v) | |||
| 737 | up_read(&namespace_sem); | 736 | up_read(&namespace_sem); |
| 738 | } | 737 | } |
| 739 | 738 | ||
| 739 | int mnt_had_events(struct proc_mounts *p) | ||
| 740 | { | ||
| 741 | struct mnt_namespace *ns = p->ns; | ||
| 742 | int res = 0; | ||
| 743 | |||
| 744 | spin_lock(&vfsmount_lock); | ||
| 745 | if (p->event != ns->event) { | ||
| 746 | p->event = ns->event; | ||
| 747 | res = 1; | ||
| 748 | } | ||
| 749 | spin_unlock(&vfsmount_lock); | ||
| 750 | |||
| 751 | return res; | ||
| 752 | } | ||
| 753 | |||
| 740 | struct proc_fs_info { | 754 | struct proc_fs_info { |
| 741 | int flag; | 755 | int flag; |
| 742 | const char *str; | 756 | const char *str; |
| @@ -1102,8 +1116,6 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
| 1102 | retval = 0; | 1116 | retval = 0; |
| 1103 | } | 1117 | } |
| 1104 | spin_unlock(&vfsmount_lock); | 1118 | spin_unlock(&vfsmount_lock); |
| 1105 | if (retval) | ||
| 1106 | security_sb_umount_busy(mnt); | ||
| 1107 | up_write(&namespace_sem); | 1119 | up_write(&namespace_sem); |
| 1108 | release_mounts(&umount_list); | 1120 | release_mounts(&umount_list); |
| 1109 | return retval; | 1121 | return retval; |
| @@ -1121,8 +1133,15 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) | |||
| 1121 | { | 1133 | { |
| 1122 | struct path path; | 1134 | struct path path; |
| 1123 | int retval; | 1135 | int retval; |
| 1136 | int lookup_flags = 0; | ||
| 1137 | |||
| 1138 | if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) | ||
| 1139 | return -EINVAL; | ||
| 1140 | |||
| 1141 | if (!(flags & UMOUNT_NOFOLLOW)) | ||
| 1142 | lookup_flags |= LOOKUP_FOLLOW; | ||
| 1124 | 1143 | ||
| 1125 | retval = user_path(name, &path); | 1144 | retval = user_path_at(AT_FDCWD, name, lookup_flags, &path); |
| 1126 | if (retval) | 1145 | if (retval) |
| 1127 | goto out; | 1146 | goto out; |
| 1128 | retval = -EINVAL; | 1147 | retval = -EINVAL; |
| @@ -1246,6 +1265,21 @@ void drop_collected_mounts(struct vfsmount *mnt) | |||
| 1246 | release_mounts(&umount_list); | 1265 | release_mounts(&umount_list); |
| 1247 | } | 1266 | } |
| 1248 | 1267 | ||
| 1268 | int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, | ||
| 1269 | struct vfsmount *root) | ||
| 1270 | { | ||
| 1271 | struct vfsmount *mnt; | ||
| 1272 | int res = f(root, arg); | ||
| 1273 | if (res) | ||
| 1274 | return res; | ||
| 1275 | list_for_each_entry(mnt, &root->mnt_list, mnt_list) { | ||
| 1276 | res = f(mnt, arg); | ||
| 1277 | if (res) | ||
| 1278 | return res; | ||
| 1279 | } | ||
| 1280 | return 0; | ||
| 1281 | } | ||
| 1282 | |||
| 1249 | static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) | 1283 | static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) |
| 1250 | { | 1284 | { |
| 1251 | struct vfsmount *p; | 1285 | struct vfsmount *p; |
| @@ -1395,20 +1429,13 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) | |||
| 1395 | 1429 | ||
| 1396 | err = -ENOENT; | 1430 | err = -ENOENT; |
| 1397 | mutex_lock(&path->dentry->d_inode->i_mutex); | 1431 | mutex_lock(&path->dentry->d_inode->i_mutex); |
| 1398 | if (IS_DEADDIR(path->dentry->d_inode)) | 1432 | if (cant_mount(path->dentry)) |
| 1399 | goto out_unlock; | 1433 | goto out_unlock; |
| 1400 | 1434 | ||
| 1401 | err = security_sb_check_sb(mnt, path); | ||
| 1402 | if (err) | ||
| 1403 | goto out_unlock; | ||
| 1404 | |||
| 1405 | err = -ENOENT; | ||
| 1406 | if (!d_unlinked(path->dentry)) | 1435 | if (!d_unlinked(path->dentry)) |
| 1407 | err = attach_recursive_mnt(mnt, path, NULL); | 1436 | err = attach_recursive_mnt(mnt, path, NULL); |
| 1408 | out_unlock: | 1437 | out_unlock: |
| 1409 | mutex_unlock(&path->dentry->d_inode->i_mutex); | 1438 | mutex_unlock(&path->dentry->d_inode->i_mutex); |
| 1410 | if (!err) | ||
| 1411 | security_sb_post_addmount(mnt, path); | ||
| 1412 | return err; | 1439 | return err; |
| 1413 | } | 1440 | } |
| 1414 | 1441 | ||
| @@ -1538,14 +1565,12 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
| 1538 | err = do_remount_sb(sb, flags, data, 0); | 1565 | err = do_remount_sb(sb, flags, data, 0); |
| 1539 | if (!err) { | 1566 | if (!err) { |
| 1540 | spin_lock(&vfsmount_lock); | 1567 | spin_lock(&vfsmount_lock); |
| 1541 | mnt_flags |= path->mnt->mnt_flags & MNT_PNODE_MASK; | 1568 | mnt_flags |= path->mnt->mnt_flags & MNT_PROPAGATION_MASK; |
| 1542 | path->mnt->mnt_flags = mnt_flags; | 1569 | path->mnt->mnt_flags = mnt_flags; |
| 1543 | spin_unlock(&vfsmount_lock); | 1570 | spin_unlock(&vfsmount_lock); |
| 1544 | } | 1571 | } |
| 1545 | up_write(&sb->s_umount); | 1572 | up_write(&sb->s_umount); |
| 1546 | if (!err) { | 1573 | if (!err) { |
| 1547 | security_sb_post_remount(path->mnt, flags, data); | ||
| 1548 | |||
| 1549 | spin_lock(&vfsmount_lock); | 1574 | spin_lock(&vfsmount_lock); |
| 1550 | touch_mnt_namespace(path->mnt->mnt_ns); | 1575 | touch_mnt_namespace(path->mnt->mnt_ns); |
| 1551 | spin_unlock(&vfsmount_lock); | 1576 | spin_unlock(&vfsmount_lock); |
| @@ -1586,7 +1611,7 @@ static int do_move_mount(struct path *path, char *old_name) | |||
| 1586 | 1611 | ||
| 1587 | err = -ENOENT; | 1612 | err = -ENOENT; |
| 1588 | mutex_lock(&path->dentry->d_inode->i_mutex); | 1613 | mutex_lock(&path->dentry->d_inode->i_mutex); |
| 1589 | if (IS_DEADDIR(path->dentry->d_inode)) | 1614 | if (cant_mount(path->dentry)) |
| 1590 | goto out1; | 1615 | goto out1; |
| 1591 | 1616 | ||
| 1592 | if (d_unlinked(path->dentry)) | 1617 | if (d_unlinked(path->dentry)) |
| @@ -1671,7 +1696,7 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path, | |||
| 1671 | { | 1696 | { |
| 1672 | int err; | 1697 | int err; |
| 1673 | 1698 | ||
| 1674 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD); | 1699 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL); |
| 1675 | 1700 | ||
| 1676 | down_write(&namespace_sem); | 1701 | down_write(&namespace_sem); |
| 1677 | /* Something was mounted here while we slept */ | 1702 | /* Something was mounted here while we slept */ |
| @@ -2197,7 +2222,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
| 2197 | if (!check_mnt(root.mnt)) | 2222 | if (!check_mnt(root.mnt)) |
| 2198 | goto out2; | 2223 | goto out2; |
| 2199 | error = -ENOENT; | 2224 | error = -ENOENT; |
| 2200 | if (IS_DEADDIR(new.dentry->d_inode)) | 2225 | if (cant_mount(old.dentry)) |
| 2201 | goto out2; | 2226 | goto out2; |
| 2202 | if (d_unlinked(new.dentry)) | 2227 | if (d_unlinked(new.dentry)) |
| 2203 | goto out2; | 2228 | goto out2; |
| @@ -2240,7 +2265,6 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
| 2240 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 2265 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
| 2241 | spin_unlock(&vfsmount_lock); | 2266 | spin_unlock(&vfsmount_lock); |
| 2242 | chroot_fs_refs(&root, &new); | 2267 | chroot_fs_refs(&root, &new); |
| 2243 | security_sb_post_pivotroot(&root, &new); | ||
| 2244 | error = 0; | 2268 | error = 0; |
| 2245 | path_put(&root_parent); | 2269 | path_put(&root_parent); |
| 2246 | path_put(&parent_path); | 2270 | path_put(&parent_path); |
| @@ -2314,17 +2338,13 @@ void __init mnt_init(void) | |||
| 2314 | 2338 | ||
| 2315 | void put_mnt_ns(struct mnt_namespace *ns) | 2339 | void put_mnt_ns(struct mnt_namespace *ns) |
| 2316 | { | 2340 | { |
| 2317 | struct vfsmount *root; | ||
| 2318 | LIST_HEAD(umount_list); | 2341 | LIST_HEAD(umount_list); |
| 2319 | 2342 | ||
| 2320 | if (!atomic_dec_and_lock(&ns->count, &vfsmount_lock)) | 2343 | if (!atomic_dec_and_test(&ns->count)) |
| 2321 | return; | 2344 | return; |
| 2322 | root = ns->root; | ||
| 2323 | ns->root = NULL; | ||
| 2324 | spin_unlock(&vfsmount_lock); | ||
| 2325 | down_write(&namespace_sem); | 2345 | down_write(&namespace_sem); |
| 2326 | spin_lock(&vfsmount_lock); | 2346 | spin_lock(&vfsmount_lock); |
| 2327 | umount_tree(root, 0, &umount_list); | 2347 | umount_tree(ns->root, 0, &umount_list); |
| 2328 | spin_unlock(&vfsmount_lock); | 2348 | spin_unlock(&vfsmount_lock); |
| 2329 | up_write(&namespace_sem); | 2349 | up_write(&namespace_sem); |
| 2330 | release_mounts(&umount_list); | 2350 | release_mounts(&umount_list); |
