|
@@ -1483,6 +1483,23 @@ out_unlock:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Sanity check the flags to change_mnt_propagation.
|
|
|
+ */
|
|
|
+
|
|
|
+static int flags_to_propagation_type(int flags)
|
|
|
+{
|
|
|
+ int type = flags & ~MS_REC;
|
|
|
+
|
|
|
+ /* Fail if any non-propagation flags are set */
|
|
|
+ if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
|
|
|
+ return 0;
|
|
|
+ /* Only one propagation flag should be set */
|
|
|
+ if (!is_power_of_2(type))
|
|
|
+ return 0;
|
|
|
+ return type;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* recursively change the type of the mountpoint.
|
|
|
*/
|
|
@@ -1490,7 +1507,7 @@ static int do_change_type(struct path *path, int flag)
|
|
|
{
|
|
|
struct vfsmount *m, *mnt = path->mnt;
|
|
|
int recurse = flag & MS_REC;
|
|
|
- int type = flag & ~MS_REC;
|
|
|
+ int type;
|
|
|
int err = 0;
|
|
|
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
@@ -1499,6 +1516,10 @@ static int do_change_type(struct path *path, int flag)
|
|
|
if (path->dentry != path->mnt->mnt_root)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ type = flags_to_propagation_type(flag);
|
|
|
+ if (!type)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
down_write(&namespace_sem);
|
|
|
if (type == MS_SHARED) {
|
|
|
err = invent_group_ids(mnt, recurse);
|