]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
UBUNTU: SAUCE: overlayfs: ensure mounter privileges when reading directories
authorAndy Whitcroft <apw@canonical.com>
Fri, 19 Oct 2018 16:45:00 +0000 (18:45 +0200)
committerThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Fri, 9 Nov 2018 19:00:55 +0000 (17:00 -0200)
BugLink: https://launchpad.net/bugs/1793458
When reading directory contents ensure the mounter has permissions for
the operation over the constituent parts (lower and upper). Where we are
in a namespace this ensures that the mounter (root in that namespace)
has permissions over the files and directories, preventing exposure of
protected files and directory contents.

CVE-2018-6559

Signed-off-by: Andy Whitcroft <apw@canonical.com>
[tyhicks: make use of new upstream check in ovl_permission() for copy-ups]
[tyhicks: make use of creator (mounter) creds hanging off the super block]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
fs/overlayfs/inode.c
fs/overlayfs/overlayfs.h
fs/overlayfs/readdir.c
fs/overlayfs/util.c

index 0dbbfedef54c04b62fb2b6ff70da69b34207cc80..21905e30f50d68b553b72881fc9c3c4f6c704228 100644 (file)
@@ -171,7 +171,6 @@ int ovl_permission(struct inode *inode, int mask)
 {
        struct inode *upperinode = ovl_inode_upper(inode);
        struct inode *realinode = upperinode ?: ovl_inode_lower(inode);
-       const struct cred *old_cred;
        int err;
 
        /* Careful in RCU walk mode */
@@ -188,15 +187,13 @@ int ovl_permission(struct inode *inode, int mask)
        if (err)
                return err;
 
-       old_cred = ovl_override_creds(inode->i_sb);
        if (!upperinode &&
            !special_file(realinode->i_mode) && mask & MAY_WRITE) {
                mask &= ~(MAY_WRITE | MAY_APPEND);
                /* Make sure mounter can read file for copy up later */
                mask |= MAY_READ;
        }
-       err = inode_permission(realinode, mask);
-       revert_creds(old_cred);
+       err = ovl_creator_permission(inode->i_sb, realinode, mask);
 
        return err;
 }
index b1917c414e933fc7b0beaec6a5ec46d2e026a098..7b06983a84476d8aa3d9ca9d97e354e982bcb1f6 100644 (file)
@@ -204,6 +204,8 @@ void ovl_drop_write(struct dentry *dentry);
 struct dentry *ovl_workdir(struct dentry *dentry);
 const struct cred *ovl_override_creds(struct super_block *sb);
 struct super_block *ovl_same_sb(struct super_block *sb);
+int ovl_creator_permission(struct super_block *sb, struct inode *inode,
+                          int mode);
 bool ovl_can_decode_fh(struct super_block *sb);
 struct dentry *ovl_indexdir(struct super_block *sb);
 struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
index e258c234f357f1c8b9c263f9527b9c596819c89f..fa946932533440b37e8d32fd4fd43c3570919be5 100644 (file)
@@ -369,6 +369,12 @@ static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list,
                next = ovl_path_next(idx, dentry, &realpath);
                rdd.is_upper = ovl_dentry_upper(dentry) == realpath.dentry;
 
+               err = ovl_creator_permission(dentry->d_sb,
+                                            d_inode(realpath.dentry),
+                                            MAY_READ);
+               if (err)
+                       break;
+
                if (next != -1) {
                        err = ovl_dir_read(&realpath, &rdd);
                        if (err)
@@ -688,6 +694,12 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
                ovl_dir_reset(file);
 
        if (od->is_real) {
+               err = ovl_creator_permission(dentry->d_sb,
+                                            file_inode(od->realfile),
+                                            MAY_READ);
+               if (err)
+                       return err;
+
                /*
                 * If parent is merge, then need to adjust d_ino for '..', if
                 * dir is impure then need to adjust d_ino for copied up
index 06119f34a69da74c24a1e36b839032bd81ceda45..ea2c28fd7be505b46837d20b4f7ea2be63b9a9ef 100644 (file)
@@ -50,6 +50,19 @@ struct super_block *ovl_same_sb(struct super_block *sb)
        return ofs->same_sb;
 }
 
+int ovl_creator_permission(struct super_block *sb, struct inode *inode,
+                          int mode)
+{
+       const struct cred *old_cred;
+       int err = 0;
+
+       old_cred = ovl_override_creds(sb);
+       err = inode_permission(inode, mode);
+       revert_creds(old_cred);
+
+       return err;
+}
+
 bool ovl_can_decode_fh(struct super_block *sb)
 {
        return (sb->s_export_op && sb->s_export_op->fh_to_dentry &&