diff options
Diffstat (limited to 'fs/overlayfs/util.c')
-rw-r--r-- | fs/overlayfs/util.c | 96 |
1 files changed, 50 insertions, 46 deletions
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 56c1f89f20c9..23f475627d07 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -544,11 +544,11 @@ void ovl_copy_up_end(struct dentry *dentry) ovl_inode_unlock(d_inode(dentry)); } -bool ovl_check_origin_xattr(struct dentry *dentry) +bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry) { int res; - res = vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0); + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_ORIGIN, NULL, 0); /* Zero size value means "copied up but origin unknown" */ if (res >= 0) @@ -557,7 +557,8 @@ bool ovl_check_origin_xattr(struct dentry *dentry) return false; } -bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) +bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry, + enum ovl_xattr ox) { int res; char val; @@ -565,15 +566,36 @@ bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) if (!d_is_dir(dentry)) return false; - res = vfs_getxattr(dentry, name, &val, 1); + res = ovl_do_getxattr(OVL_FS(sb), dentry, ox, &val, 1); if (res == 1 && val == 'y') return true; return false; } +#define OVL_XATTR_OPAQUE_POSTFIX "opaque" +#define OVL_XATTR_REDIRECT_POSTFIX "redirect" +#define OVL_XATTR_ORIGIN_POSTFIX "origin" +#define OVL_XATTR_IMPURE_POSTFIX "impure" +#define OVL_XATTR_NLINK_POSTFIX "nlink" +#define OVL_XATTR_UPPER_POSTFIX "upper" +#define OVL_XATTR_METACOPY_POSTFIX "metacopy" + +#define OVL_XATTR_TAB_ENTRY(x) \ + [x] = OVL_XATTR_PREFIX x ## _POSTFIX + +const char *ovl_xattr_table[] = { + OVL_XATTR_TAB_ENTRY(OVL_XATTR_OPAQUE), + OVL_XATTR_TAB_ENTRY(OVL_XATTR_REDIRECT), + OVL_XATTR_TAB_ENTRY(OVL_XATTR_ORIGIN), + OVL_XATTR_TAB_ENTRY(OVL_XATTR_IMPURE), + OVL_XATTR_TAB_ENTRY(OVL_XATTR_NLINK), + OVL_XATTR_TAB_ENTRY(OVL_XATTR_UPPER), + OVL_XATTR_TAB_ENTRY(OVL_XATTR_METACOPY), +}; + int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, - const char *name, const void *value, size_t size, + enum ovl_xattr ox, const void *value, size_t size, int xerr) { int err; @@ -582,10 +604,10 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, if (ofs->noxattr) return xerr; - err = ovl_do_setxattr(upperdentry, name, value, size, 0); + err = ovl_do_setxattr(ofs, upperdentry, ox, value, size); if (err == -EOPNOTSUPP) { - pr_warn("cannot set %s xattr on upper\n", name); + pr_warn("cannot set %s xattr on upper\n", ovl_xattr(ofs, ox)); ofs->noxattr = true; return xerr; } @@ -845,7 +867,7 @@ err: } /* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */ -int ovl_check_metacopy_xattr(struct dentry *dentry) +int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry) { int res; @@ -853,7 +875,7 @@ int ovl_check_metacopy_xattr(struct dentry *dentry) if (!S_ISREG(d_inode(dentry)->i_mode)) return 0; - res = vfs_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0); + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0); if (res < 0) { if (res == -ENODATA || res == -EOPNOTSUPP) return 0; @@ -882,49 +904,27 @@ 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("failed to get xattr %s: err=%zi)\n", - name, res); - kfree(buf); - return res; -} - -char *ovl_get_redirect_xattr(struct dentry *dentry, int padding) +char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry, + int padding) { int res; char *s, *next, *buf = NULL; - res = ovl_getxattr(dentry, OVL_XATTR_REDIRECT, &buf, padding + 1); - if (res == -ENODATA) + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0); + if (res == -ENODATA || res == -EOPNOTSUPP) return NULL; if (res < 0) - return ERR_PTR(res); + goto fail; + if (res == 0) + goto invalid; + + buf = kzalloc(res + padding + 1, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + + res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res); + if (res < 0) + goto fail; if (res == 0) goto invalid; @@ -943,6 +943,10 @@ char *ovl_get_redirect_xattr(struct dentry *dentry, int padding) invalid: pr_warn_ratelimited("invalid redirect (%s)\n", buf); res = -EINVAL; + goto err_free; +fail: + pr_warn_ratelimited("failed to get redirect (%i)\n", res); +err_free: kfree(buf); return ERR_PTR(res); } |