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:
commit
236bfd8ed8
2 changed files with 33 additions and 8 deletions
|
@ -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 */
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue