aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-12 17:48:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-12 17:48:52 -0400
commitf88c5942cfaf7d55e46d395136cccaca65b2e3bf (patch)
tree33640d03b5d3652c41bb09b49d85af2b3659b820
parentdfee9c257b102d7c0407629eef2ed32e152de0d2 (diff)
parent993a0b2aec52754f0897b1dab4c453be8217cae5 (diff)
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
-rw-r--r--fs/overlayfs/copy_up.c59
-rw-r--r--fs/overlayfs/overlayfs.h2
-rw-r--r--fs/overlayfs/util.c55
3 files changed, 81 insertions, 35 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 9e62dcf06fc4..68b3303e4b46 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -443,6 +443,24 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
443{ 443{
444 int err; 444 int err;
445 445
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
446 err = ovl_copy_xattr(c->lowerpath.dentry, temp); 464 err = ovl_copy_xattr(c->lowerpath.dentry, temp);
447 if (err) 465 if (err)
448 return err; 466 return err;
@@ -460,19 +478,6 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
460 return err; 478 return err;
461 } 479 }
462 480
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
476 if (c->metacopy) { 481 if (c->metacopy) {
477 err = ovl_check_setxattr(c->dentry, temp, OVL_XATTR_METACOPY, 482 err = ovl_check_setxattr(c->dentry, temp, OVL_XATTR_METACOPY,
478 NULL, 0, -EOPNOTSUPP); 483 NULL, 0, -EOPNOTSUPP);
@@ -737,6 +742,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
737{ 742{
738 struct path upperpath, datapath; 743 struct path upperpath, datapath;
739 int err; 744 int err;
745 char *capability = NULL;
746 ssize_t uninitialized_var(cap_size);
740 747
741 ovl_path_upper(c->dentry, &upperpath); 748 ovl_path_upper(c->dentry, &upperpath);
742 if (WARN_ON(upperpath.dentry == NULL)) 749 if (WARN_ON(upperpath.dentry == NULL))
@@ -746,15 +753,37 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
746 if (WARN_ON(datapath.dentry == NULL)) 753 if (WARN_ON(datapath.dentry == NULL))
747 return -EIO; 754 return -EIO;
748 755
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
749 err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size); 763 err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
750 if (err) 764 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
752 778
753 err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY); 779 err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY);
754 if (err) 780 if (err)
755 return err; 781 goto out_free;
756 782
757 ovl_set_upperdata(d_inode(c->dentry)); 783 ovl_set_upperdata(d_inode(c->dentry));
784out_free:
785 kfree(capability);
786out:
758 return err; 787 return err;
759} 788}
760 789
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 5e45cb3630a0..9c6018287d57 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -277,6 +277,8 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
277int ovl_check_metacopy_xattr(struct dentry *dentry); 277int ovl_check_metacopy_xattr(struct dentry *dentry);
278bool ovl_is_metacopy_dentry(struct dentry *dentry); 278bool ovl_is_metacopy_dentry(struct dentry *dentry);
279char *ovl_get_redirect_xattr(struct dentry *dentry, int padding); 279char *ovl_get_redirect_xattr(struct dentry *dentry, int padding);
280ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
281 size_t padding);
280 282
281static inline bool ovl_is_impuredir(struct dentry *dentry) 283static inline bool ovl_is_impuredir(struct dentry *dentry)
282{ 284{
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 7c01327b1852..4035e640f402 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -863,28 +863,49 @@ bool ovl_is_metacopy_dentry(struct dentry *dentry)
863 return (oe->numlower > 1); 863 return (oe->numlower > 1);
864} 864}
865 865
866char *ovl_get_redirect_xattr(struct dentry *dentry, int padding) 866ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
867 size_t padding)
867{ 868{
868 int res; 869 ssize_t res;
869 char *s, *next, *buf = NULL; 870 char *buf = NULL;
870 871
871 res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0); 872 res = vfs_getxattr(dentry, name, NULL, 0);
872 if (res < 0) { 873 if (res < 0) {
873 if (res == -ENODATA || res == -EOPNOTSUPP) 874 if (res == -ENODATA || res == -EOPNOTSUPP)
874 return NULL; 875 return -ENODATA;
875 goto fail; 876 goto fail;
876 } 877 }
877 878
878 buf = kzalloc(res + padding + 1, GFP_KERNEL); 879 if (res != 0) {
879 if (!buf) 880 buf = kzalloc(res + padding, GFP_KERNEL);
880 return ERR_PTR(-ENOMEM); 881 if (!buf)
882 return -ENOMEM;
881 883
882 if (res == 0) 884 res = vfs_getxattr(dentry, name, buf, res);
883 goto invalid; 885 if (res < 0)
886 goto fail;
887 }
888 *value = buf;
889
890 return res;
891
892fail:
893 pr_warn_ratelimited("overlayfs: failed to get xattr %s: err=%zi)\n",
894 name, res);
895 kfree(buf);
896 return res;
897}
884 898
885 res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res); 899char *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;
886 if (res < 0) 907 if (res < 0)
887 goto fail; 908 return ERR_PTR(res);
888 if (res == 0) 909 if (res == 0)
889 goto invalid; 910 goto invalid;
890 911
@@ -900,15 +921,9 @@ char *ovl_get_redirect_xattr(struct dentry *dentry, int padding)
900 } 921 }
901 922
902 return buf; 923 return buf;
903
904err_free:
905 kfree(buf);
906 return ERR_PTR(res);
907fail:
908 pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res);
909 goto err_free;
910invalid: 924invalid:
911 pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf); 925 pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf);
912 res = -EINVAL; 926 res = -EINVAL;
913 goto err_free; 927 kfree(buf);
928 return ERR_PTR(res);
914} 929}