Skip to content

Commit

Permalink
mnt: fs_fully_visible enforce noexec and nosuid if !SB_I_NOEXEC
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Eric W. Biederman committed Jul 10, 2015
1 parent 90f8572 commit 77b1a97
Showing 1 changed file with 25 additions and 8 deletions.
33 changes: 25 additions & 8 deletions fs/namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -3194,6 +3194,8 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
down_read(&namespace_sem);
list_for_each_entry(mnt, &ns->list, mnt_list) {
struct mount *child;
int mnt_flags;

if (mnt->mnt.mnt_sb->s_type != type)
continue;

Expand All @@ -3203,17 +3205,30 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root)
continue;

/* Read the mount flags and filter out flags that
* may safely be ignored.
*/
mnt_flags = mnt->mnt.mnt_flags;
if (mnt->mnt.mnt_sb->s_iflags & SB_I_NOEXEC)
mnt_flags &= ~(MNT_LOCK_NOSUID | MNT_LOCK_NOEXEC);

/* Verify the mount flags are equal to or more permissive
* than the proposed new mount.
*/
if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) &&
if ((mnt_flags & MNT_LOCK_READONLY) &&
!(new_flags & MNT_READONLY))
continue;
if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
if ((mnt_flags & MNT_LOCK_NODEV) &&
!(new_flags & MNT_NODEV))
continue;
if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) &&
((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
if ((mnt_flags & MNT_LOCK_NOSUID) &&
!(new_flags & MNT_NOSUID))
continue;
if ((mnt_flags & MNT_LOCK_NOEXEC) &&
!(new_flags & MNT_NOEXEC))
continue;
if ((mnt_flags & MNT_LOCK_ATIME) &&
((mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
continue;

/* This mount is not fully visible if there are any
Expand All @@ -3223,16 +3238,18 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
struct inode *inode = child->mnt_mountpoint->d_inode;
/* Only worry about locked mounts */
if (!(mnt->mnt.mnt_flags & MNT_LOCKED))
if (!(mnt_flags & MNT_LOCKED))
continue;
/* Is the directory permanetly empty? */
if (!is_empty_dir_inode(inode))
goto next;
}
/* Preserve the locked attributes */
*new_mnt_flags |= mnt->mnt.mnt_flags & (MNT_LOCK_READONLY | \
MNT_LOCK_NODEV | \
MNT_LOCK_ATIME);
*new_mnt_flags |= mnt_flags & (MNT_LOCK_READONLY | \
MNT_LOCK_NODEV | \
MNT_LOCK_NOSUID | \
MNT_LOCK_NOEXEC | \
MNT_LOCK_ATIME);
visible = true;
goto found;
next: ;
Expand Down

0 comments on commit 77b1a97

Please sign in to comment.