]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszer...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 3 Jul 2016 18:57:09 +0000 (11:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 3 Jul 2016 18:57:09 +0000 (11:57 -0700)
Pull overlayfs fixes from Miklos Szeredi:
 "This contains fixes for a dentry leak, a regression in 4.6 noticed by
  Docker users and missing write access checking in truncate"

* 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
  ovl: warn instead of error if d_type is not supported
  ovl: get_write_access() in truncate
  ovl: fix dentry leak for default_permissions

fs/overlayfs/inode.c
fs/overlayfs/super.c

index 1dbeab6cf96e54c7e43cf040ef3d909ce6fe2071..c831c2e5f803f26d553264b3a2fc2abbe38803e9 100644 (file)
@@ -59,16 +59,37 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
        if (err)
                goto out;
 
+       if (attr->ia_valid & ATTR_SIZE) {
+               struct inode *realinode = d_inode(ovl_dentry_real(dentry));
+
+               err = -ETXTBSY;
+               if (atomic_read(&realinode->i_writecount) < 0)
+                       goto out_drop_write;
+       }
+
        err = ovl_copy_up(dentry);
        if (!err) {
+               struct inode *winode = NULL;
+
                upperdentry = ovl_dentry_upper(dentry);
 
+               if (attr->ia_valid & ATTR_SIZE) {
+                       winode = d_inode(upperdentry);
+                       err = get_write_access(winode);
+                       if (err)
+                               goto out_drop_write;
+               }
+
                inode_lock(upperdentry->d_inode);
                err = notify_change(upperdentry, attr, NULL);
                if (!err)
                        ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
                inode_unlock(upperdentry->d_inode);
+
+               if (winode)
+                       put_write_access(winode);
        }
+out_drop_write:
        ovl_drop_write(dentry);
 out:
        return err;
@@ -121,16 +142,18 @@ int ovl_permission(struct inode *inode, int mask)
 
                err = vfs_getattr(&realpath, &stat);
                if (err)
-                       return err;
+                       goto out_dput;
 
+               err = -ESTALE;
                if ((stat.mode ^ inode->i_mode) & S_IFMT)
-                       return -ESTALE;
+                       goto out_dput;
 
                inode->i_mode = stat.mode;
                inode->i_uid = stat.uid;
                inode->i_gid = stat.gid;
 
-               return generic_permission(inode, mask);
+               err = generic_permission(inode, mask);
+               goto out_dput;
        }
 
        /* Careful in RCU walk mode */
index ce02f46029da7c3aa7c69be9291d62c81baeb642..9a7693d5f8fffb38bd4a07804e4627ed7f50361a 100644 (file)
@@ -1082,11 +1082,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                        if (err < 0)
                                goto out_put_workdir;
 
-                       if (!err) {
-                               pr_err("overlayfs: upper fs needs to support d_type.\n");
-                               err = -EINVAL;
-                               goto out_put_workdir;
-                       }
+                       /*
+                        * We allowed this configuration and don't want to
+                        * break users over kernel upgrade. So warn instead
+                        * of erroring out.
+                        */
+                       if (!err)
+                               pr_warn("overlayfs: upper fs needs to support d_type.\n");
                }
        }