|
@@ -1540,8 +1540,13 @@ static int do_umount(struct mount *mnt, int flags)
|
|
|
|
|
|
namespace_lock();
|
|
namespace_lock();
|
|
lock_mount_hash();
|
|
lock_mount_hash();
|
|
- event++;
|
|
|
|
|
|
|
|
|
|
+ /* Recheck MNT_LOCKED with the locks held */
|
|
|
|
+ retval = -EINVAL;
|
|
|
|
+ if (mnt->mnt.mnt_flags & MNT_LOCKED)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ event++;
|
|
if (flags & MNT_DETACH) {
|
|
if (flags & MNT_DETACH) {
|
|
if (!list_empty(&mnt->mnt_list))
|
|
if (!list_empty(&mnt->mnt_list))
|
|
umount_tree(mnt, UMOUNT_PROPAGATE);
|
|
umount_tree(mnt, UMOUNT_PROPAGATE);
|
|
@@ -1555,6 +1560,7 @@ static int do_umount(struct mount *mnt, int flags)
|
|
retval = 0;
|
|
retval = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+out:
|
|
unlock_mount_hash();
|
|
unlock_mount_hash();
|
|
namespace_unlock();
|
|
namespace_unlock();
|
|
return retval;
|
|
return retval;
|
|
@@ -1645,7 +1651,7 @@ int ksys_umount(char __user *name, int flags)
|
|
goto dput_and_out;
|
|
goto dput_and_out;
|
|
if (!check_mnt(mnt))
|
|
if (!check_mnt(mnt))
|
|
goto dput_and_out;
|
|
goto dput_and_out;
|
|
- if (mnt->mnt.mnt_flags & MNT_LOCKED)
|
|
|
|
|
|
+ if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
|
|
goto dput_and_out;
|
|
goto dput_and_out;
|
|
retval = -EPERM;
|
|
retval = -EPERM;
|
|
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
|
|
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
|