aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-11-23 19:34:49 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-03 22:52:36 -0500
commitafac7cba7ed31968a95e181dc25e204e45009ea8 (patch)
tree282cf7da6bc3915093df622ebfcd39f44f6fd1cd /fs/namespace.c
parentb2dba1af3c4157040303a76d25216b1713d333d0 (diff)
vfs: more mnt_parent cleanups
a) mount --move is checking that ->mnt_parent is non-NULL before looking if that parent happens to be shared; ->mnt_parent is never NULL and it's not even an misspelled !mnt_has_parent() b) pivot_root open-codes is_path_reachable(), poorly. c) so does path_is_under(), while we are at it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index ec8512478b04..7aad258dcaf6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1876,8 +1876,7 @@ static int do_move_mount(struct path *path, char *old_name)
1876 /* 1876 /*
1877 * Don't move a mount residing in a shared parent. 1877 * Don't move a mount residing in a shared parent.
1878 */ 1878 */
1879 if (old_path.mnt->mnt_parent && 1879 if (IS_MNT_SHARED(old_path.mnt->mnt_parent))
1880 IS_MNT_SHARED(old_path.mnt->mnt_parent))
1881 goto out1; 1880 goto out1;
1882 /* 1881 /*
1883 * Don't move a mount tree containing unbindable mounts to a destination 1882 * Don't move a mount tree containing unbindable mounts to a destination
@@ -2534,6 +2533,31 @@ out_type:
2534} 2533}
2535 2534
2536/* 2535/*
2536 * Return true if path is reachable from root
2537 *
2538 * namespace_sem or vfsmount_lock is held
2539 */
2540bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
2541 const struct path *root)
2542{
2543 while (mnt != root->mnt && mnt_has_parent(mnt)) {
2544 dentry = mnt->mnt_mountpoint;
2545 mnt = mnt->mnt_parent;
2546 }
2547 return mnt == root->mnt && is_subdir(dentry, root->dentry);
2548}
2549
2550int path_is_under(struct path *path1, struct path *path2)
2551{
2552 int res;
2553 br_read_lock(vfsmount_lock);
2554 res = is_path_reachable(path1->mnt, path1->dentry, path2);
2555 br_read_unlock(vfsmount_lock);
2556 return res;
2557}
2558EXPORT_SYMBOL(path_is_under);
2559
2560/*
2537 * pivot_root Semantics: 2561 * pivot_root Semantics:
2538 * Moves the root file system of the current process to the directory put_old, 2562 * Moves the root file system of the current process to the directory put_old,
2539 * makes new_root as the new root file system of the current process, and sets 2563 * makes new_root as the new root file system of the current process, and sets
@@ -2561,7 +2585,6 @@ out_type:
2561SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, 2585SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
2562 const char __user *, put_old) 2586 const char __user *, put_old)
2563{ 2587{
2564 struct vfsmount *tmp;
2565 struct path new, old, parent_path, root_parent, root; 2588 struct path new, old, parent_path, root_parent, root;
2566 int error; 2589 int error;
2567 2590
@@ -2611,18 +2634,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
2611 if (!mnt_has_parent(new.mnt)) 2634 if (!mnt_has_parent(new.mnt))
2612 goto out4; /* not attached */ 2635 goto out4; /* not attached */
2613 /* make sure we can reach put_old from new_root */ 2636 /* make sure we can reach put_old from new_root */
2614 tmp = old.mnt; 2637 if (!is_path_reachable(old.mnt, old.dentry, &new))
2615 if (tmp != new.mnt) {
2616 for (;;) {
2617 if (!mnt_has_parent(tmp))
2618 goto out4; /* already mounted on put_old */
2619 if (tmp->mnt_parent == new.mnt)
2620 break;
2621 tmp = tmp->mnt_parent;
2622 }
2623 if (!is_subdir(tmp->mnt_mountpoint, new.dentry))
2624 goto out4;
2625 } else if (!is_subdir(old.dentry, new.dentry))
2626 goto out4; 2638 goto out4;
2627 br_write_lock(vfsmount_lock); 2639 br_write_lock(vfsmount_lock);
2628 detach_mnt(new.mnt, &parent_path); 2640 detach_mnt(new.mnt, &parent_path);