aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2015-05-09 00:49:47 -0400
committerEric W. Biederman <ebiederm@xmission.com>2015-06-04 11:29:25 -0400
commit8c6cf9cc829fcd0b179b59f7fe288941d0e31108 (patch)
treeda5901e5d3b6cc41d7ea30d1fc39be7244254019
parent1b852bceb0d111e510d1a15826ecc4a19358d512 (diff)
mnt: Modify fs_fully_visible to deal with locked ro nodev and atime
Ignore an existing mount if the locked readonly, nodev or atime attributes are less permissive than the desired attributes of the new mount. On success ensure the new mount locks all of the same readonly, nodev and atime attributes as the old mount. The nosuid and noexec attributes are not checked here as this change is destined for stable and enforcing those attributes causes a regression in lxc and libvirt-lxc where those applications will not start and there are no known executables on sysfs or proc and no known way to create exectuables without code modifications Cc: stable@vger.kernel.org Fixes: e51db73532955 ("userns: Better restrictions on when proc and sysfs can be mounted") Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-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: ;