]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
UBUNTU: SAUCE: overlayfs: Propogate nosuid from lower and upper mounts
authorSeth Forshee <seth.forshee@canonical.com>
Thu, 21 Jan 2016 21:37:53 +0000 (15:37 -0600)
committerSeth Forshee <seth.forshee@canonical.com>
Mon, 29 Jan 2018 13:44:53 +0000 (07:44 -0600)
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>
fs/exec.c
fs/overlayfs/super.c
include/linux/fs.h
security/commoncap.c
security/selinux/hooks.c

index ad22775b6da97abcd6366497fe3ca9c58959a894..c248c185f66f26122fb273afa7b1176ada41a609 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -112,6 +112,13 @@ bool path_noexec(const struct path *path)
               (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
@@ -1511,7 +1518,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
        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))
index 76440feb79f64ee0fce36713ed4fe4264ff70f11..024cbe288b3358df74d64826eeaa4f54920e3564 100644 (file)
@@ -1058,8 +1058,8 @@ out:
        return err;
 }
 
-static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
-                               unsigned int numlower)
+static int ovl_get_lower_layers(struct super_block *sb, struct ovl_fs *ofs,
+                               struct path *stack, unsigned int numlower)
 {
        int err;
        unsigned int i;
@@ -1092,6 +1092,13 @@ static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
                 */
                mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME;
 
+               /*
+                * If any lower mount is nosuid, force the ovl sb to also
+                * be nosuid.
+                */
+               if (mnt->mnt_flags & MNT_NOSUID)
+                       sb->s_iflags |= SB_I_NOSUID;
+
                ofs->lower_layers[ofs->numlower].mnt = mnt;
                ofs->lower_layers[ofs->numlower].pseudo_dev = dev;
                ofs->numlower++;
@@ -1156,7 +1163,7 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
                goto out_err;
        }
 
-       err = ovl_get_lower_layers(ofs, stack, numlower);
+       err = ovl_get_lower_layers(sb, ofs, stack, numlower);
        if (err)
                goto out_err;
 
@@ -1237,6 +1244,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                if (!ofs->workdir)
                        sb->s_flags |= SB_RDONLY;
 
+               /*
+                * If the upper mount is nosuid, force the ovl sb to also
+                * be nosuid.
+                */
+               if (ofs->upper_mnt->mnt_flags & MNT_NOSUID)
+                       sb->s_iflags |= SB_I_NOSUID;
+
                sb->s_stack_depth = ofs->upper_mnt->mnt_sb->s_stack_depth;
                sb->s_time_gran = ofs->upper_mnt->mnt_sb->s_time_gran;
 
index 511fbaabf6248b67220c16653e491f74e3f046e7..ddbcbfa486fd840488af67296cba6ea2ef6cef1d 100644 (file)
@@ -1312,6 +1312,7 @@ extern int send_sigurg(struct fown_struct *fown);
 #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 */
@@ -3408,6 +3409,7 @@ static inline bool dir_relax_shared(struct inode *inode)
 }
 
 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 */
index 48620c93d6976eca3a9b1cc3c34cfe21a69c7a39..f3d3fa01e789bd237b09911f49165afa17ddf2e6 100644 (file)
@@ -660,7 +660,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_f
        if (!file_caps_enabled)
                return 0;
 
-       if (!mnt_may_suid(bprm->file->f_path.mnt))
+       if (path_nosuid(&bprm->file->f_path))
                return 0;
 
        /*
index 8644d864e3c196ca3dc8a10cb84c2daa97e3a596..0c8e0cf122ab7cfd2a805cca3eabe5a0af8452ae 100644 (file)
@@ -2335,7 +2335,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
                            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;
        u32 av;