An overlayfs mount using an upper or lower directory from a
nosuid filesystem bypasses this restriction. Change this so
that if any lower or upper directory is nosuid at mount time the
overlayfs superblock is marked nosuid. This requires some
additions at the vfs level since nosuid currently only applies to
mounts, so a SB_I_NOSUID flag is added along with a helper
function to check a path for nosuid in both the mount and the
superblock.
BugLink: http://bugs.launchpad.net/bugs/1534961
BugLink: http://bugs.launchpad.net/bugs/1535150
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
}
+bool path_nosuid(const struct path *path)
+{
+ return !mnt_may_suid(path->mnt) ||
+ (path->mnt->mnt_sb->s_iflags & SB_I_NOSUID);
+}
+EXPORT_SYMBOL(path_nosuid);
+
#ifdef CONFIG_USELIB
/*
* Note that a shared library must be both readable and executable due to
bprm->cred->euid = current_euid();
bprm->cred->egid = current_egid();
- if (!mnt_may_suid(bprm->file->f_path.mnt))
+ if (path_nosuid(&bprm->file->f_path))
return;
if (task_no_new_privs(current))
sb->s_time_gran = ufs->upper_mnt->mnt_sb->s_time_gran;
+ if (ufs->upper_mnt->mnt_flags & MNT_NOSUID)
+ sb->s_iflags |= SB_I_NOSUID;
+
ufs->workdir = ovl_workdir_create(sb, ufs, workpath.dentry,
OVL_WORKDIR_NAME, false);
/*
*/
mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME;
+ if (mnt->mnt_flags & MNT_NOSUID)
+ sb->s_iflags |= SB_I_NOSUID;
+
ufs->lower_mnt[ufs->numlower] = mnt;
ufs->numlower++;
#define SB_I_CGROUPWB 0x00000001 /* cgroup-aware writeback enabled */
#define SB_I_NOEXEC 0x00000002 /* Ignore executables on this fs */
#define SB_I_NODEV 0x00000004 /* Ignore devices on this fs */
+#define SB_I_NOSUID 0x00000008 /* Ignore suid on this fs */
/* sb->s_iflags to limit user namespace mounts */
#define SB_I_USERNS_VISIBLE 0x00000010 /* fstype already mounted */
}
extern bool path_noexec(const struct path *path);
+extern bool path_nosuid(const struct path *path);
extern void inode_nohighmem(struct inode *inode);
#endif /* _LINUX_FS_H */
if (!file_caps_enabled)
return 0;
- if (!mnt_may_suid(bprm->file->f_path.mnt))
+ if (path_nosuid(&bprm->file->f_path))
return 0;
/*
const struct task_security_struct *new_tsec)
{
int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
- int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
+ int nosuid = path_nosuid(&bprm->file->f_path);
int rc;
if (!nnp && !nosuid)