aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namespace.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 8e7edaf60fe1..63b9806235e6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2332,7 +2332,7 @@ unlock:
2332 return err; 2332 return err;
2333} 2333}
2334 2334
2335static bool fs_fully_visible(struct file_system_type *fs_type); 2335static bool fs_fully_visible(struct file_system_type *fs_type, int *new_mnt_flags);
2336 2336
2337/* 2337/*
2338 * create a new mount for userspace and request it to be added into the 2338 * create a new mount for userspace and request it to be added into the
@@ -2366,7 +2366,7 @@ static int do_new_mount(struct path *path, const char *fstype, int flags,
2366 mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV; 2366 mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
2367 } 2367 }
2368 if (type->fs_flags & FS_USERNS_VISIBLE) { 2368 if (type->fs_flags & FS_USERNS_VISIBLE) {
2369 if (!fs_fully_visible(type)) 2369 if (!fs_fully_visible(type, &mnt_flags))
2370 return -EPERM; 2370 return -EPERM;
2371 } 2371 }
2372 } 2372 }
@@ -3170,9 +3170,10 @@ bool current_chrooted(void)
3170 return chrooted; 3170 return chrooted;
3171} 3171}
3172 3172
3173static bool fs_fully_visible(struct file_system_type *type) 3173static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
3174{ 3174{
3175 struct mnt_namespace *ns = current->nsproxy->mnt_ns; 3175 struct mnt_namespace *ns = current->nsproxy->mnt_ns;
3176 int new_flags = *new_mnt_flags;
3176 struct mount *mnt; 3177 struct mount *mnt;
3177 bool visible = false; 3178 bool visible = false;
3178 3179
@@ -3191,6 +3192,19 @@ static bool fs_fully_visible(struct file_system_type *type)
3191 if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root) 3192 if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root)
3192 continue; 3193 continue;
3193 3194
3195 /* Verify the mount flags are equal to or more permissive
3196 * than the proposed new mount.
3197 */
3198 if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) &&
3199 !(new_flags & MNT_READONLY))
3200 continue;
3201 if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
3202 !(new_flags & MNT_NODEV))
3203 continue;
3204 if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) &&
3205 ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
3206 continue;
3207
3194 /* This mount is not fully visible if there are any child mounts 3208 /* This mount is not fully visible if there are any child mounts
3195 * that cover anything except for empty directories. 3209 * that cover anything except for empty directories.
3196 */ 3210 */
@@ -3201,6 +3215,10 @@ static bool fs_fully_visible(struct file_system_type *type)
3201 if (inode->i_nlink > 2) 3215 if (inode->i_nlink > 2)
3202 goto next; 3216 goto next;
3203 } 3217 }
3218 /* Preserve the locked attributes */
3219 *new_mnt_flags |= mnt->mnt.mnt_flags & (MNT_LOCK_READONLY | \
3220 MNT_LOCK_NODEV | \
3221 MNT_LOCK_ATIME);
3204 visible = true; 3222 visible = true;
3205 goto found; 3223 goto found;
3206 next: ; 3224 next: ;