]> git.proxmox.com Git - mirror_ubuntu-focal-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)
committerAndrea Righi <andrea.righi@canonical.com>
Mon, 25 Nov 2019 13:56:27 +0000 (14:56 +0100)
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 9d148db170683a28372bec48e3873cc2162b820e..fa5edf6f62e26f343f57963dd72893c1981f6336 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -113,6 +113,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
@@ -1531,7 +1538,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 afbcb116a7f1b8d1f26eafcd94c7064bd58b56ef..3a6da8046981bdc45c8e010221b4c5f05a8d9d9f 100644 (file)
@@ -1359,6 +1359,14 @@ static int ovl_get_lower_layers(struct super_block *sb, struct ovl_fs *ofs,
                mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME;
 
                ofs->lower_layers[ofs->numlower].trap = trap;
+
+               /*
+                * 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].idx = i + 1;
                ofs->lower_layers[ofs->numlower].fsid = fsid;
@@ -1615,6 +1623,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 e0d909d357634bb26a9adfa65ddbcc9bce5364f6..555b51bcd9d4d085d469fd20c1c36af3818b15d4 100644 (file)
@@ -1397,6 +1397,7 @@ extern int send_sigurg(struct fown_struct *fown);
 #define SB_I_NOEXEC    0x00000002      /* Ignore executables on this fs */
 #define SB_I_NODEV     0x00000004      /* Ignore devices on this fs */
 #define SB_I_MULTIROOT 0x00000008      /* Multiple roots to the dentry tree */
+#define SB_I_NOSUID    0x00000010      /* Ignore suid on this fs */
 
 /* sb->s_iflags to limit user namespace mounts */
 #define SB_I_USERNS_VISIBLE            0x00000010 /* fstype already mounted */
@@ -3580,6 +3581,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);
 
 /* mm/fadvise.c */
index f4ee0ae106b282a12adb338f8caa6ce219cfbceb..1f03083192bdc08a5b333c9e1709fa9dba29a62f 100644 (file)
@@ -657,7 +657,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 9625b99e677fd33cf4abc1ebcc48fb3b79fb44d8..3b03667f69f6ae14f567578404b97c4277f60d59 100644 (file)
@@ -2277,7 +2277,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;