aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/overlayfs/copy_up.c28
-rw-r--r--fs/overlayfs/overlayfs.h2
-rw-r--r--fs/overlayfs/util.c55
3 files changed, 63 insertions, 22 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 48119b23375b..68b3303e4b46 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -742,6 +742,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
742{ 742{
743 struct path upperpath, datapath; 743 struct path upperpath, datapath;
744 int err; 744 int err;
745 char *capability = NULL;
746 ssize_t uninitialized_var(cap_size);
745 747
746 ovl_path_upper(c->dentry, &upperpath); 748 ovl_path_upper(c->dentry, &upperpath);
747 if (WARN_ON(upperpath.dentry == NULL)) 749 if (WARN_ON(upperpath.dentry == NULL))
@@ -751,15 +753,37 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
751 if (WARN_ON(datapath.dentry == NULL)) 753 if (WARN_ON(datapath.dentry == NULL))
752 return -EIO; 754 return -EIO;
753 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
754 err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size); 763 err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
755 if (err) 764 if (err)
756 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
757 778
758 err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY); 779 err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY);
759 if (err) 780 if (err)
760 return err; 781 goto out_free;
761 782
762 ovl_set_upperdata(d_inode(c->dentry)); 783 ovl_set_upperdata(d_inode(c->dentry));
784out_free:
785 kfree(capability);
786out:
763 return err; 787 return err;
764} 788}
765 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}