Skip to content

Commit f88c594

Browse files
committed
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
2 parents dfee9c2 + 993a0b2 commit f88c594

File tree

3 files changed

+81
-35
lines changed

3 files changed

+81
-35
lines changed

fs/overlayfs/copy_up.c

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,24 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
443443
{
444444
int err;
445445

446+
/*
447+
* Copy up data first and then xattrs. Writing data after
448+
* xattrs will remove security.capability xattr automatically.
449+
*/
450+
if (S_ISREG(c->stat.mode) && !c->metacopy) {
451+
struct path upperpath, datapath;
452+
453+
ovl_path_upper(c->dentry, &upperpath);
454+
if (WARN_ON(upperpath.dentry != NULL))
455+
return -EIO;
456+
upperpath.dentry = temp;
457+
458+
ovl_path_lowerdata(c->dentry, &datapath);
459+
err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
460+
if (err)
461+
return err;
462+
}
463+
446464
err = ovl_copy_xattr(c->lowerpath.dentry, temp);
447465
if (err)
448466
return err;
@@ -460,19 +478,6 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
460478
return err;
461479
}
462480

463-
if (S_ISREG(c->stat.mode) && !c->metacopy) {
464-
struct path upperpath, datapath;
465-
466-
ovl_path_upper(c->dentry, &upperpath);
467-
BUG_ON(upperpath.dentry != NULL);
468-
upperpath.dentry = temp;
469-
470-
ovl_path_lowerdata(c->dentry, &datapath);
471-
err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
472-
if (err)
473-
return err;
474-
}
475-
476481
if (c->metacopy) {
477482
err = ovl_check_setxattr(c->dentry, temp, OVL_XATTR_METACOPY,
478483
NULL, 0, -EOPNOTSUPP);
@@ -737,6 +742,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
737742
{
738743
struct path upperpath, datapath;
739744
int err;
745+
char *capability = NULL;
746+
ssize_t uninitialized_var(cap_size);
740747

741748
ovl_path_upper(c->dentry, &upperpath);
742749
if (WARN_ON(upperpath.dentry == NULL))
@@ -746,15 +753,37 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
746753
if (WARN_ON(datapath.dentry == NULL))
747754
return -EIO;
748755

756+
if (c->stat.size) {
757+
err = cap_size = ovl_getxattr(upperpath.dentry, XATTR_NAME_CAPS,
758+
&capability, 0);
759+
if (err < 0 && err != -ENODATA)
760+
goto out;
761+
}
762+
749763
err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
750764
if (err)
751-
return err;
765+
goto out_free;
766+
767+
/*
768+
* Writing to upper file will clear security.capability xattr. We
769+
* don't want that to happen for normal copy-up operation.
770+
*/
771+
if (capability) {
772+
err = ovl_do_setxattr(upperpath.dentry, XATTR_NAME_CAPS,
773+
capability, cap_size, 0);
774+
if (err)
775+
goto out_free;
776+
}
777+
752778

753779
err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY);
754780
if (err)
755-
return err;
781+
goto out_free;
756782

757783
ovl_set_upperdata(d_inode(c->dentry));
784+
out_free:
785+
kfree(capability);
786+
out:
758787
return err;
759788
}
760789

fs/overlayfs/overlayfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
277277
int ovl_check_metacopy_xattr(struct dentry *dentry);
278278
bool ovl_is_metacopy_dentry(struct dentry *dentry);
279279
char *ovl_get_redirect_xattr(struct dentry *dentry, int padding);
280+
ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
281+
size_t padding);
280282

281283
static inline bool ovl_is_impuredir(struct dentry *dentry)
282284
{

fs/overlayfs/util.c

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -863,28 +863,49 @@ bool ovl_is_metacopy_dentry(struct dentry *dentry)
863863
return (oe->numlower > 1);
864864
}
865865

866-
char *ovl_get_redirect_xattr(struct dentry *dentry, int padding)
866+
ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
867+
size_t padding)
867868
{
868-
int res;
869-
char *s, *next, *buf = NULL;
869+
ssize_t res;
870+
char *buf = NULL;
870871

871-
res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0);
872+
res = vfs_getxattr(dentry, name, NULL, 0);
872873
if (res < 0) {
873874
if (res == -ENODATA || res == -EOPNOTSUPP)
874-
return NULL;
875+
return -ENODATA;
875876
goto fail;
876877
}
877878

878-
buf = kzalloc(res + padding + 1, GFP_KERNEL);
879-
if (!buf)
880-
return ERR_PTR(-ENOMEM);
879+
if (res != 0) {
880+
buf = kzalloc(res + padding, GFP_KERNEL);
881+
if (!buf)
882+
return -ENOMEM;
881883

882-
if (res == 0)
883-
goto invalid;
884+
res = vfs_getxattr(dentry, name, buf, res);
885+
if (res < 0)
886+
goto fail;
887+
}
888+
*value = buf;
889+
890+
return res;
891+
892+
fail:
893+
pr_warn_ratelimited("overlayfs: failed to get xattr %s: err=%zi)\n",
894+
name, res);
895+
kfree(buf);
896+
return res;
897+
}
884898

885-
res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res);
899+
char *ovl_get_redirect_xattr(struct dentry *dentry, int padding)
900+
{
901+
int res;
902+
char *s, *next, *buf = NULL;
903+
904+
res = ovl_getxattr(dentry, OVL_XATTR_REDIRECT, &buf, padding + 1);
905+
if (res == -ENODATA)
906+
return NULL;
886907
if (res < 0)
887-
goto fail;
908+
return ERR_PTR(res);
888909
if (res == 0)
889910
goto invalid;
890911

@@ -900,15 +921,9 @@ char *ovl_get_redirect_xattr(struct dentry *dentry, int padding)
900921
}
901922

902923
return buf;
903-
904-
err_free:
905-
kfree(buf);
906-
return ERR_PTR(res);
907-
fail:
908-
pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res);
909-
goto err_free;
910924
invalid:
911925
pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf);
912926
res = -EINVAL;
913-
goto err_free;
927+
kfree(buf);
928+
return ERR_PTR(res);
914929
}

0 commit comments

Comments
 (0)