aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2015-06-04 10:43:11 -0400
committerEric W. Biederman <ebiederm@xmission.com>2015-07-10 11:41:13 -0400
commit77b1a97d218277d55a15016826d1fd79290f1df2 (patch)
tree0b973e720d2b550196010a683a19eb21f77a3d22
parent90f8572b0f021fdd1baa68e00a8c30482ee9e5f4 (diff)
mnt: fs_fully_visible enforce noexec and nosuid if !SB_I_NOEXEC
The filesystems proc and sysfs do not have executable files do not have exectuable files today and portions of userspace break if we do enforce nosuid and noexec consistency of nosuid and noexec flags between previous mounts and new mounts of proc and sysfs. Add the code to enforce consistency of the nosuid and noexec flags, and use the presence of SB_I_NOEXEC to signal that there is no need to bother. This results in a completely userspace invisible change that makes it clear fs_fully_visible can only skip the enforcement of noexec and nosuid because it is known the filesystems in question do not support executables. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--fs/namespace.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index c7cb8a526c05..ce428cadd41f 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3194,6 +3194,8 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
3194 down_read(&namespace_sem); 3194 down_read(&namespace_sem);
3195 list_for_each_entry(mnt, &ns->list, mnt_list) { 3195 list_for_each_entry(mnt, &ns->list, mnt_list) {
3196 struct mount *child; 3196 struct mount *child;
3197 int mnt_flags;
3198
3197 if (mnt->mnt.mnt_sb->s_type != type) 3199 if (mnt->mnt.mnt_sb->s_type != type)
3198 continue; 3200 continue;
3199 3201
@@ -3203,17 +3205,30 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
3203 if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root) 3205 if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root)
3204 continue; 3206 continue;
3205 3207
3208 /* Read the mount flags and filter out flags that
3209 * may safely be ignored.
3210 */
3211 mnt_flags = mnt->mnt.mnt_flags;
3212 if (mnt->mnt.mnt_sb->s_iflags & SB_I_NOEXEC)
3213 mnt_flags &= ~(MNT_LOCK_NOSUID | MNT_LOCK_NOEXEC);
3214
3206 /* Verify the mount flags are equal to or more permissive 3215 /* Verify the mount flags are equal to or more permissive
3207 * than the proposed new mount. 3216 * than the proposed new mount.
3208 */ 3217 */
3209 if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) && 3218 if ((mnt_flags & MNT_LOCK_READONLY) &&
3210 !(new_flags & MNT_READONLY)) 3219 !(new_flags & MNT_READONLY))
3211 continue; 3220 continue;
3212 if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) && 3221 if ((mnt_flags & MNT_LOCK_NODEV) &&
3213 !(new_flags & MNT_NODEV)) 3222 !(new_flags & MNT_NODEV))
3214 continue; 3223 continue;
3215 if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) && 3224 if ((mnt_flags & MNT_LOCK_NOSUID) &&
3216 ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK))) 3225 !(new_flags & MNT_NOSUID))
3226 continue;
3227 if ((mnt_flags & MNT_LOCK_NOEXEC) &&
3228 !(new_flags & MNT_NOEXEC))
3229 continue;
3230 if ((mnt_flags & MNT_LOCK_ATIME) &&
3231 ((mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
3217 continue; 3232 continue;
3218 3233
3219 /* This mount is not fully visible if there are any 3234 /* This mount is not fully visible if there are any
@@ -3223,16 +3238,18 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
3223 list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) { 3238 list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
3224 struct inode *inode = child->mnt_mountpoint->d_inode; 3239 struct inode *inode = child->mnt_mountpoint->d_inode;
3225 /* Only worry about locked mounts */ 3240 /* Only worry about locked mounts */
3226 if (!(mnt->mnt.mnt_flags & MNT_LOCKED)) 3241 if (!(mnt_flags & MNT_LOCKED))
3227 continue; 3242 continue;
3228 /* Is the directory permanetly empty? */ 3243 /* Is the directory permanetly empty? */
3229 if (!is_empty_dir_inode(inode)) 3244 if (!is_empty_dir_inode(inode))
3230 goto next; 3245 goto next;
3231 } 3246 }
3232 /* Preserve the locked attributes */ 3247 /* Preserve the locked attributes */
3233 *new_mnt_flags |= mnt->mnt.mnt_flags & (MNT_LOCK_READONLY | \ 3248 *new_mnt_flags |= mnt_flags & (MNT_LOCK_READONLY | \
3234 MNT_LOCK_NODEV | \ 3249 MNT_LOCK_NODEV | \
3235 MNT_LOCK_ATIME); 3250 MNT_LOCK_NOSUID | \
3251 MNT_LOCK_NOEXEC | \
3252 MNT_LOCK_ATIME);
3236 visible = true; 3253 visible = true;
3237 goto found; 3254 goto found;
3238 next: ; 3255 next: ;