Commit a0a6df9a authored by Al Viro's avatar Al Viro
Browse files

umount(2): move the flag validity checks first



Unfortunately, there's userland code that used to rely upon these
checks being done before anything else to check for UMOUNT_NOFOLLOW
support.  That broke in 41525f56 ("fs: refactor ksys_umount").
Separate those from the rest of checks and move them to ksys_umount();
unlike everything else in there, this can be sanely done there.

Reported-by: default avatarSargun Dhillon <sargun@sargun.me>
Fixes: 41525f56 ("fs: refactor ksys_umount")
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 5c8fe583
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -1713,8 +1713,6 @@ static int can_umount(const struct path *path, int flags)
{
	struct mount *mnt = real_mount(path->mnt);

	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
		return -EINVAL;
	if (!may_mount())
		return -EPERM;
	if (path->dentry != path->mnt->mnt_root)
@@ -1728,6 +1726,7 @@ static int can_umount(const struct path *path, int flags)
	return 0;
}

// caller is responsible for flags being sane
int path_umount(struct path *path, int flags)
{
	struct mount *mnt = real_mount(path->mnt);
@@ -1749,6 +1748,10 @@ static int ksys_umount(char __user *name, int flags)
	struct path path;
	int ret;

	// basic validity checks done first
	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
		return -EINVAL;

	if (!(flags & UMOUNT_NOFOLLOW))
		lookup_flags |= LOOKUP_FOLLOW;
	ret = user_path_at(AT_FDCWD, name, lookup_flags, &path);