forked from Minki/linux
overlayfs update for 5.1
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQSQHSd0lITzzeNWNm3h3BK/laaZPAUCXIdy6QAKCRDh3BK/laaZ PByaAP4i2zjNXfp5AJ7CbBgOmA92QeeNeUexAz7cZb9SKCWHCwEA+yyCWXTn+PlM OF2OU+nmH7btbo0kwMhdKKtdOocGMAQ= =58lL -----END PGP SIGNATURE----- Merge tag 'ovl-update-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs Pull overlayfs updates from Miklos Szeredi: "Fix copy up of security related xattrs" * tag 'ovl-update-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: Do not lose security.capability xattr over metadata file copy-up ovl: During copy up, first copy up data and then xattrs
This commit is contained in:
commit
f88c5942cf
@ -443,6 +443,24 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
|
||||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Copy up data first and then xattrs. Writing data after
|
||||
* xattrs will remove security.capability xattr automatically.
|
||||
*/
|
||||
if (S_ISREG(c->stat.mode) && !c->metacopy) {
|
||||
struct path upperpath, datapath;
|
||||
|
||||
ovl_path_upper(c->dentry, &upperpath);
|
||||
if (WARN_ON(upperpath.dentry != NULL))
|
||||
return -EIO;
|
||||
upperpath.dentry = temp;
|
||||
|
||||
ovl_path_lowerdata(c->dentry, &datapath);
|
||||
err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = ovl_copy_xattr(c->lowerpath.dentry, temp);
|
||||
if (err)
|
||||
return err;
|
||||
@ -460,19 +478,6 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (S_ISREG(c->stat.mode) && !c->metacopy) {
|
||||
struct path upperpath, datapath;
|
||||
|
||||
ovl_path_upper(c->dentry, &upperpath);
|
||||
BUG_ON(upperpath.dentry != NULL);
|
||||
upperpath.dentry = temp;
|
||||
|
||||
ovl_path_lowerdata(c->dentry, &datapath);
|
||||
err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (c->metacopy) {
|
||||
err = ovl_check_setxattr(c->dentry, temp, OVL_XATTR_METACOPY,
|
||||
NULL, 0, -EOPNOTSUPP);
|
||||
@ -737,6 +742,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
|
||||
{
|
||||
struct path upperpath, datapath;
|
||||
int err;
|
||||
char *capability = NULL;
|
||||
ssize_t uninitialized_var(cap_size);
|
||||
|
||||
ovl_path_upper(c->dentry, &upperpath);
|
||||
if (WARN_ON(upperpath.dentry == NULL))
|
||||
@ -746,15 +753,37 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
|
||||
if (WARN_ON(datapath.dentry == NULL))
|
||||
return -EIO;
|
||||
|
||||
if (c->stat.size) {
|
||||
err = cap_size = ovl_getxattr(upperpath.dentry, XATTR_NAME_CAPS,
|
||||
&capability, 0);
|
||||
if (err < 0 && err != -ENODATA)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
|
||||
if (err)
|
||||
return err;
|
||||
goto out_free;
|
||||
|
||||
/*
|
||||
* Writing to upper file will clear security.capability xattr. We
|
||||
* don't want that to happen for normal copy-up operation.
|
||||
*/
|
||||
if (capability) {
|
||||
err = ovl_do_setxattr(upperpath.dentry, XATTR_NAME_CAPS,
|
||||
capability, cap_size, 0);
|
||||
if (err)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
||||
err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY);
|
||||
if (err)
|
||||
return err;
|
||||
goto out_free;
|
||||
|
||||
ovl_set_upperdata(d_inode(c->dentry));
|
||||
out_free:
|
||||
kfree(capability);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -277,6 +277,8 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
|
||||
int ovl_check_metacopy_xattr(struct dentry *dentry);
|
||||
bool ovl_is_metacopy_dentry(struct dentry *dentry);
|
||||
char *ovl_get_redirect_xattr(struct dentry *dentry, int padding);
|
||||
ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
|
||||
size_t padding);
|
||||
|
||||
static inline bool ovl_is_impuredir(struct dentry *dentry)
|
||||
{
|
||||
|
@ -863,28 +863,49 @@ bool ovl_is_metacopy_dentry(struct dentry *dentry)
|
||||
return (oe->numlower > 1);
|
||||
}
|
||||
|
||||
ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
|
||||
size_t padding)
|
||||
{
|
||||
ssize_t res;
|
||||
char *buf = NULL;
|
||||
|
||||
res = vfs_getxattr(dentry, name, NULL, 0);
|
||||
if (res < 0) {
|
||||
if (res == -ENODATA || res == -EOPNOTSUPP)
|
||||
return -ENODATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (res != 0) {
|
||||
buf = kzalloc(res + padding, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
res = vfs_getxattr(dentry, name, buf, res);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
}
|
||||
*value = buf;
|
||||
|
||||
return res;
|
||||
|
||||
fail:
|
||||
pr_warn_ratelimited("overlayfs: failed to get xattr %s: err=%zi)\n",
|
||||
name, res);
|
||||
kfree(buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *ovl_get_redirect_xattr(struct dentry *dentry, int padding)
|
||||
{
|
||||
int res;
|
||||
char *s, *next, *buf = NULL;
|
||||
|
||||
res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0);
|
||||
if (res < 0) {
|
||||
if (res == -ENODATA || res == -EOPNOTSUPP)
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
buf = kzalloc(res + padding + 1, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (res == 0)
|
||||
goto invalid;
|
||||
|
||||
res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res);
|
||||
res = ovl_getxattr(dentry, OVL_XATTR_REDIRECT, &buf, padding + 1);
|
||||
if (res == -ENODATA)
|
||||
return NULL;
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
return ERR_PTR(res);
|
||||
if (res == 0)
|
||||
goto invalid;
|
||||
|
||||
@ -900,15 +921,9 @@ char *ovl_get_redirect_xattr(struct dentry *dentry, int padding)
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
err_free:
|
||||
kfree(buf);
|
||||
return ERR_PTR(res);
|
||||
fail:
|
||||
pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res);
|
||||
goto err_free;
|
||||
invalid:
|
||||
pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf);
|
||||
res = -EINVAL;
|
||||
goto err_free;
|
||||
kfree(buf);
|
||||
return ERR_PTR(res);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user