Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs

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
This commit is contained in:
Linus Torvalds 2016-07-03 11:57:09 -07:00
commit 236bfd8ed8
2 changed files with 33 additions and 8 deletions

View file

@ -59,16 +59,37 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
if (err) if (err)
goto out; 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); err = ovl_copy_up(dentry);
if (!err) { if (!err) {
struct inode *winode = NULL;
upperdentry = ovl_dentry_upper(dentry); 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); inode_lock(upperdentry->d_inode);
err = notify_change(upperdentry, attr, NULL); err = notify_change(upperdentry, attr, NULL);
if (!err) if (!err)
ovl_copyattr(upperdentry->d_inode, dentry->d_inode); ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
inode_unlock(upperdentry->d_inode); inode_unlock(upperdentry->d_inode);
if (winode)
put_write_access(winode);
} }
out_drop_write:
ovl_drop_write(dentry); ovl_drop_write(dentry);
out: out:
return err; return err;
@ -121,16 +142,18 @@ int ovl_permission(struct inode *inode, int mask)
err = vfs_getattr(&realpath, &stat); err = vfs_getattr(&realpath, &stat);
if (err) if (err)
return err; goto out_dput;
err = -ESTALE;
if ((stat.mode ^ inode->i_mode) & S_IFMT) if ((stat.mode ^ inode->i_mode) & S_IFMT)
return -ESTALE; goto out_dput;
inode->i_mode = stat.mode; inode->i_mode = stat.mode;
inode->i_uid = stat.uid; inode->i_uid = stat.uid;
inode->i_gid = stat.gid; inode->i_gid = stat.gid;
return generic_permission(inode, mask); err = generic_permission(inode, mask);
goto out_dput;
} }
/* Careful in RCU walk mode */ /* Careful in RCU walk mode */

View file

@ -1082,11 +1082,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
if (err < 0) if (err < 0)
goto out_put_workdir; goto out_put_workdir;
if (!err) { /*
pr_err("overlayfs: upper fs needs to support d_type.\n"); * We allowed this configuration and don't want to
err = -EINVAL; * break users over kernel upgrade. So warn instead
goto out_put_workdir; * of erroring out.
} */
if (!err)
pr_warn("overlayfs: upper fs needs to support d_type.\n");
} }
} }