Merge branch 'akpm' (patches from Andrew)
[linux-2.6-microblaze.git] / fs / namespace.c
index 94a9817..659a8f3 100644 (file)
@@ -1716,22 +1716,14 @@ static inline bool may_mount(void)
        return ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN);
 }
 
-#ifdef CONFIG_MANDATORY_FILE_LOCKING
-static bool may_mandlock(void)
+static void warn_mandlock(void)
 {
-       pr_warn_once("======================================================\n"
-                    "WARNING: the mand mount option is being deprecated and\n"
-                    "         will be removed in v5.15!\n"
-                    "======================================================\n");
-       return capable(CAP_SYS_ADMIN);
+       pr_warn_once("=======================================================\n"
+                    "WARNING: The mand mount option has been deprecated and\n"
+                    "         and is ignored by this kernel. Remove the mand\n"
+                    "         option from the mount to silence this warning.\n"
+                    "=======================================================\n");
 }
-#else
-static inline bool may_mandlock(void)
-{
-       pr_warn("VFS: \"mand\" mount option not supported");
-       return false;
-}
-#endif
 
 static int can_umount(const struct path *path, int flags)
 {
@@ -2703,6 +2695,78 @@ out:
        return ret;
 }
 
+static int do_set_group(struct path *from_path, struct path *to_path)
+{
+       struct mount *from, *to;
+       int err;
+
+       from = real_mount(from_path->mnt);
+       to = real_mount(to_path->mnt);
+
+       namespace_lock();
+
+       err = -EINVAL;
+       /* To and From must be mounted */
+       if (!is_mounted(&from->mnt))
+               goto out;
+       if (!is_mounted(&to->mnt))
+               goto out;
+
+       err = -EPERM;
+       /* We should be allowed to modify mount namespaces of both mounts */
+       if (!ns_capable(from->mnt_ns->user_ns, CAP_SYS_ADMIN))
+               goto out;
+       if (!ns_capable(to->mnt_ns->user_ns, CAP_SYS_ADMIN))
+               goto out;
+
+       err = -EINVAL;
+       /* To and From paths should be mount roots */
+       if (from_path->dentry != from_path->mnt->mnt_root)
+               goto out;
+       if (to_path->dentry != to_path->mnt->mnt_root)
+               goto out;
+
+       /* Setting sharing groups is only allowed across same superblock */
+       if (from->mnt.mnt_sb != to->mnt.mnt_sb)
+               goto out;
+
+       /* From mount root should be wider than To mount root */
+       if (!is_subdir(to->mnt.mnt_root, from->mnt.mnt_root))
+               goto out;
+
+       /* From mount should not have locked children in place of To's root */
+       if (has_locked_children(from, to->mnt.mnt_root))
+               goto out;
+
+       /* Setting sharing groups is only allowed on private mounts */
+       if (IS_MNT_SHARED(to) || IS_MNT_SLAVE(to))
+               goto out;
+
+       /* From should not be private */
+       if (!IS_MNT_SHARED(from) && !IS_MNT_SLAVE(from))
+               goto out;
+
+       if (IS_MNT_SLAVE(from)) {
+               struct mount *m = from->mnt_master;
+
+               list_add(&to->mnt_slave, &m->mnt_slave_list);
+               to->mnt_master = m;
+       }
+
+       if (IS_MNT_SHARED(from)) {
+               to->mnt_group_id = from->mnt_group_id;
+               list_add(&to->mnt_share, &from->mnt_share);
+               lock_mount_hash();
+               set_mnt_shared(to);
+               unlock_mount_hash();
+       }
+
+       err = 0;
+out:
+       namespace_unlock();
+       return err;
+}
+
 static int do_move_mount(struct path *old_path, struct path *new_path)
 {
        struct mnt_namespace *ns;
@@ -3198,8 +3262,8 @@ int path_mount(const char *dev_name, struct path *path,
                return ret;
        if (!may_mount())
                return -EPERM;
-       if ((flags & SB_MANDLOCK) && !may_mandlock())
-               return -EPERM;
+       if (flags & SB_MANDLOCK)
+               warn_mandlock();
 
        /* Default to relatime unless overriden */
        if (!(flags & MS_NOATIME))
@@ -3582,9 +3646,8 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags,
        if (fc->phase != FS_CONTEXT_AWAITING_MOUNT)
                goto err_unlock;
 
-       ret = -EPERM;
-       if ((fc->sb_flags & SB_MANDLOCK) && !may_mandlock())
-               goto err_unlock;
+       if (fc->sb_flags & SB_MANDLOCK)
+               warn_mandlock();
 
        newmount.mnt = vfs_create_mount(fc);
        if (IS_ERR(newmount.mnt)) {
@@ -3688,7 +3751,10 @@ SYSCALL_DEFINE5(move_mount,
        if (ret < 0)
                goto out_to;
 
-       ret = do_move_mount(&from_path, &to_path);
+       if (flags & MOVE_MOUNT_SET_GROUP)
+               ret = do_set_group(&from_path, &to_path);
+       else
+               ret = do_move_mount(&from_path, &to_path);
 
 out_to:
        path_put(&to_path);