Commit 610afc0b authored by Miklos Szeredi's avatar Miklos Szeredi

ovl: pass ovl_fs down to functions accessing private xattrs

This paves the way for optionally using the "user.overlay." xattr
namespace.
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 26150ab5
...@@ -43,7 +43,8 @@ static bool ovl_must_copy_xattr(const char *name) ...@@ -43,7 +43,8 @@ static bool ovl_must_copy_xattr(const char *name)
!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN); !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN);
} }
int ovl_copy_xattr(struct dentry *old, struct dentry *new) int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
struct dentry *new)
{ {
ssize_t list_size, size, value_size = 0; ssize_t list_size, size, value_size = 0;
char *buf, *name, *value = NULL; char *buf, *name, *value = NULL;
...@@ -81,7 +82,7 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new) ...@@ -81,7 +82,7 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
} }
list_size -= slen; list_size -= slen;
if (ovl_is_private_xattr(name)) if (ovl_is_private_xattr(sb, name))
continue; continue;
retry: retry:
size = vfs_getxattr(old, name, value, value_size); size = vfs_getxattr(old, name, value, value_size);
...@@ -355,7 +356,8 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower, ...@@ -355,7 +356,8 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
} }
/* Store file handle of @upper dir in @index dir entry */ /* Store file handle of @upper dir in @index dir entry */
static int ovl_set_upper_fh(struct dentry *upper, struct dentry *index) static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper,
struct dentry *index)
{ {
const struct ovl_fh *fh; const struct ovl_fh *fh;
int err; int err;
...@@ -364,7 +366,7 @@ static int ovl_set_upper_fh(struct dentry *upper, struct dentry *index) ...@@ -364,7 +366,7 @@ static int ovl_set_upper_fh(struct dentry *upper, struct dentry *index)
if (IS_ERR(fh)) if (IS_ERR(fh))
return PTR_ERR(fh); return PTR_ERR(fh);
err = ovl_do_setxattr(index, OVL_XATTR_UPPER, fh->buf, fh->fb.len); err = ovl_do_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len);
kfree(fh); kfree(fh);
return err; return err;
...@@ -409,7 +411,7 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin, ...@@ -409,7 +411,7 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin,
if (IS_ERR(temp)) if (IS_ERR(temp))
goto free_name; goto free_name;
err = ovl_set_upper_fh(upper, temp); err = ovl_set_upper_fh(OVL_FS(dentry->d_sb), upper, temp);
if (err) if (err)
goto out; goto out;
...@@ -507,7 +509,7 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp) ...@@ -507,7 +509,7 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
return err; return err;
} }
err = ovl_copy_xattr(c->lowerpath.dentry, temp); err = ovl_copy_xattr(c->dentry->d_sb, c->lowerpath.dentry, temp);
if (err) if (err)
return err; return err;
...@@ -847,7 +849,7 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) ...@@ -847,7 +849,7 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
} }
err = ovl_do_removexattr(upperpath.dentry, OVL_XATTR_METACOPY); err = ovl_do_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY);
if (err) if (err)
goto out_free; goto out_free;
......
...@@ -394,7 +394,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, ...@@ -394,7 +394,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
if (IS_ERR(opaquedir)) if (IS_ERR(opaquedir))
goto out_unlock; goto out_unlock;
err = ovl_copy_xattr(upper, opaquedir); err = ovl_copy_xattr(dentry->d_sb, upper, opaquedir);
if (err) if (err)
goto out_cleanup; goto out_cleanup;
......
...@@ -752,7 +752,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb, ...@@ -752,7 +752,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
goto out_err; goto out_err;
} }
if (index) { if (index) {
err = ovl_verify_origin(index, origin.dentry, false); err = ovl_verify_origin(ofs, index, origin.dentry, false);
if (err) if (err)
goto out_err; goto out_err;
} }
......
...@@ -327,7 +327,7 @@ static const char *ovl_get_link(struct dentry *dentry, ...@@ -327,7 +327,7 @@ static const char *ovl_get_link(struct dentry *dentry,
return p; return p;
} }
bool ovl_is_private_xattr(const char *name) bool ovl_is_private_xattr(struct super_block *sb, const char *name)
{ {
return strncmp(name, OVL_XATTR_PREFIX, return strncmp(name, OVL_XATTR_PREFIX,
sizeof(OVL_XATTR_PREFIX) - 1) == 0; sizeof(OVL_XATTR_PREFIX) - 1) == 0;
...@@ -391,14 +391,14 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, ...@@ -391,14 +391,14 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
return res; return res;
} }
static bool ovl_can_list(const char *s) static bool ovl_can_list(struct super_block *sb, const char *s)
{ {
/* List all non-trusted xatts */ /* List all non-trusted xatts */
if (strncmp(s, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0) if (strncmp(s, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0)
return true; return true;
/* Never list trusted.overlay, list other trusted for superuser only */ /* Never list trusted.overlay, list other trusted for superuser only */
return !ovl_is_private_xattr(s) && return !ovl_is_private_xattr(sb, s) &&
ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN); ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN);
} }
...@@ -425,7 +425,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) ...@@ -425,7 +425,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
return -EIO; return -EIO;
len -= slen; len -= slen;
if (!ovl_can_list(s)) { if (!ovl_can_list(dentry->d_sb, s)) {
res -= slen; res -= slen;
memmove(s, s + slen, len); memmove(s, s + slen, len);
} else { } else {
...@@ -722,7 +722,7 @@ static int ovl_set_nlink_common(struct dentry *dentry, ...@@ -722,7 +722,7 @@ static int ovl_set_nlink_common(struct dentry *dentry,
if (WARN_ON(len >= sizeof(buf))) if (WARN_ON(len >= sizeof(buf)))
return -EIO; return -EIO;
return ovl_do_setxattr(ovl_dentry_upper(dentry), return ovl_do_setxattr(OVL_FS(inode->i_sb), ovl_dentry_upper(dentry),
OVL_XATTR_NLINK, buf, len); OVL_XATTR_NLINK, buf, len);
} }
...@@ -736,7 +736,7 @@ int ovl_set_nlink_lower(struct dentry *dentry) ...@@ -736,7 +736,7 @@ int ovl_set_nlink_lower(struct dentry *dentry)
return ovl_set_nlink_common(dentry, ovl_dentry_lower(dentry), "L%+i"); return ovl_set_nlink_common(dentry, ovl_dentry_lower(dentry), "L%+i");
} }
unsigned int ovl_get_nlink(struct dentry *lowerdentry, unsigned int ovl_get_nlink(struct ovl_fs *ofs, struct dentry *lowerdentry,
struct dentry *upperdentry, struct dentry *upperdentry,
unsigned int fallback) unsigned int fallback)
{ {
...@@ -748,7 +748,7 @@ unsigned int ovl_get_nlink(struct dentry *lowerdentry, ...@@ -748,7 +748,7 @@ unsigned int ovl_get_nlink(struct dentry *lowerdentry,
if (!lowerdentry || !upperdentry || d_inode(lowerdentry)->i_nlink == 1) if (!lowerdentry || !upperdentry || d_inode(lowerdentry)->i_nlink == 1)
return fallback; return fallback;
err = ovl_do_getxattr(upperdentry, OVL_XATTR_NLINK, err = ovl_do_getxattr(ofs, upperdentry, OVL_XATTR_NLINK,
&buf, sizeof(buf) - 1); &buf, sizeof(buf) - 1);
if (err < 0) if (err < 0)
goto fail; goto fail;
...@@ -947,6 +947,7 @@ static struct inode *ovl_iget5(struct super_block *sb, struct inode *newinode, ...@@ -947,6 +947,7 @@ static struct inode *ovl_iget5(struct super_block *sb, struct inode *newinode,
struct inode *ovl_get_inode(struct super_block *sb, struct inode *ovl_get_inode(struct super_block *sb,
struct ovl_inode_params *oip) struct ovl_inode_params *oip)
{ {
struct ovl_fs *ofs = OVL_FS(sb);
struct dentry *upperdentry = oip->upperdentry; struct dentry *upperdentry = oip->upperdentry;
struct ovl_path *lowerpath = oip->lowerpath; struct ovl_path *lowerpath = oip->lowerpath;
struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL;
...@@ -994,7 +995,8 @@ struct inode *ovl_get_inode(struct super_block *sb, ...@@ -994,7 +995,8 @@ struct inode *ovl_get_inode(struct super_block *sb,
/* Recalculate nlink for non-dir due to indexing */ /* Recalculate nlink for non-dir due to indexing */
if (!is_dir) if (!is_dir)
nlink = ovl_get_nlink(lowerdentry, upperdentry, nlink); nlink = ovl_get_nlink(ofs, lowerdentry, upperdentry,
nlink);
set_nlink(inode, nlink); set_nlink(inode, nlink);
ino = key->i_ino; ino = key->i_ino;
} else { } else {
...@@ -1010,7 +1012,7 @@ struct inode *ovl_get_inode(struct super_block *sb, ...@@ -1010,7 +1012,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev); ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev);
ovl_inode_init(inode, oip, ino, fsid); ovl_inode_init(inode, oip, ino, fsid);
if (upperdentry && ovl_is_impuredir(upperdentry)) if (upperdentry && ovl_is_impuredir(sb, upperdentry))
ovl_set_flag(OVL_IMPURE, inode); ovl_set_flag(OVL_IMPURE, inode);
if (oip->index) if (oip->index)
...@@ -1024,7 +1026,7 @@ struct inode *ovl_get_inode(struct super_block *sb, ...@@ -1024,7 +1026,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
/* Check for non-merge dir that may have whiteouts */ /* Check for non-merge dir that may have whiteouts */
if (is_dir) { if (is_dir) {
if (((upperdentry && lowerdentry) || oip->numlower > 1) || if (((upperdentry && lowerdentry) || oip->numlower > 1) ||
ovl_check_origin_xattr(upperdentry ?: lowerdentry)) { ovl_check_origin_xattr(ofs, upperdentry ?: lowerdentry)) {
ovl_set_flag(OVL_WHITEOUTS, inode); ovl_set_flag(OVL_WHITEOUTS, inode);
} }
} }
......
...@@ -30,8 +30,9 @@ static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, ...@@ -30,8 +30,9 @@ static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d,
{ {
int res; int res;
char *buf; char *buf;
struct ovl_fs *ofs = OVL_FS(d->sb);
buf = ovl_get_redirect_xattr(dentry, prelen + strlen(post)); buf = ovl_get_redirect_xattr(ofs, dentry, prelen + strlen(post));
if (IS_ERR_OR_NULL(buf)) if (IS_ERR_OR_NULL(buf))
return PTR_ERR(buf); return PTR_ERR(buf);
...@@ -104,12 +105,13 @@ int ovl_check_fb_len(struct ovl_fb *fb, int fb_len) ...@@ -104,12 +105,13 @@ int ovl_check_fb_len(struct ovl_fb *fb, int fb_len)
return 0; return 0;
} }
static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name) static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry,
const char *name)
{ {
int res, err; int res, err;
struct ovl_fh *fh = NULL; struct ovl_fh *fh = NULL;
res = ovl_do_getxattr(dentry, name, NULL, 0); res = ovl_do_getxattr(ofs, dentry, name, NULL, 0);
if (res < 0) { if (res < 0) {
if (res == -ENODATA || res == -EOPNOTSUPP) if (res == -ENODATA || res == -EOPNOTSUPP)
return NULL; return NULL;
...@@ -123,7 +125,7 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name) ...@@ -123,7 +125,7 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
if (!fh) if (!fh)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
res = ovl_do_getxattr(dentry, name, fh->buf, res); res = ovl_do_getxattr(ofs, dentry, name, fh->buf, res);
if (res < 0) if (res < 0)
goto fail; goto fail;
...@@ -186,9 +188,9 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt, ...@@ -186,9 +188,9 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
return real; return real;
} }
static bool ovl_is_opaquedir(struct dentry *dentry) static bool ovl_is_opaquedir(struct super_block *sb, struct dentry *dentry)
{ {
return ovl_check_dir_xattr(dentry, OVL_XATTR_OPAQUE); return ovl_check_dir_xattr(sb, dentry, OVL_XATTR_OPAQUE);
} }
static struct dentry *ovl_lookup_positive_unlocked(const char *name, static struct dentry *ovl_lookup_positive_unlocked(const char *name,
...@@ -251,7 +253,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, ...@@ -251,7 +253,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
d->stop = true; d->stop = true;
goto put_and_out; goto put_and_out;
} }
err = ovl_check_metacopy_xattr(this); err = ovl_check_metacopy_xattr(OVL_FS(d->sb), this);
if (err < 0) if (err < 0)
goto out_err; goto out_err;
...@@ -271,7 +273,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d, ...@@ -271,7 +273,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
if (d->last) if (d->last)
goto out; goto out;
if (ovl_is_opaquedir(this)) { if (ovl_is_opaquedir(d->sb, this)) {
d->stop = true; d->stop = true;
if (last_element) if (last_element)
d->opaque = true; d->opaque = true;
...@@ -391,7 +393,7 @@ int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected, ...@@ -391,7 +393,7 @@ int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry, static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry,
struct ovl_path **stackp) struct ovl_path **stackp)
{ {
struct ovl_fh *fh = ovl_get_fh(upperdentry, OVL_XATTR_ORIGIN); struct ovl_fh *fh = ovl_get_fh(ofs, upperdentry, OVL_XATTR_ORIGIN);
int err; int err;
if (IS_ERR_OR_NULL(fh)) if (IS_ERR_OR_NULL(fh))
...@@ -413,10 +415,10 @@ static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry, ...@@ -413,10 +415,10 @@ static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry,
* Verify that @fh matches the file handle stored in xattr @name. * Verify that @fh matches the file handle stored in xattr @name.
* Return 0 on match, -ESTALE on mismatch, < 0 on error. * Return 0 on match, -ESTALE on mismatch, < 0 on error.
*/ */
static int ovl_verify_fh(struct dentry *dentry, const char *name, static int ovl_verify_fh(struct ovl_fs *ofs, struct dentry *dentry,
const struct ovl_fh *fh) const char *name, const struct ovl_fh *fh)
{ {
struct ovl_fh *ofh = ovl_get_fh(dentry, name); struct ovl_fh *ofh = ovl_get_fh(ofs, dentry, name);
int err = 0; int err = 0;
if (!ofh) if (!ofh)
...@@ -440,8 +442,9 @@ static int ovl_verify_fh(struct dentry *dentry, const char *name, ...@@ -440,8 +442,9 @@ static int ovl_verify_fh(struct dentry *dentry, const char *name,
* *
* Return 0 on match, -ESTALE on mismatch, -ENODATA on no xattr, < 0 on error. * Return 0 on match, -ESTALE on mismatch, -ENODATA on no xattr, < 0 on error.
*/ */
int ovl_verify_set_fh(struct dentry *dentry, const char *name, int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry,
struct dentry *real, bool is_upper, bool set) const char *name, struct dentry *real, bool is_upper,
bool set)
{ {
struct inode *inode; struct inode *inode;
struct ovl_fh *fh; struct ovl_fh *fh;
...@@ -454,9 +457,9 @@ int ovl_verify_set_fh(struct dentry *dentry, const char *name, ...@@ -454,9 +457,9 @@ int ovl_verify_set_fh(struct dentry *dentry, const char *name,
goto fail; goto fail;
} }
err = ovl_verify_fh(dentry, name, fh); err = ovl_verify_fh(ofs, dentry, name, fh);
if (set && err == -ENODATA) if (set && err == -ENODATA)
err = ovl_do_setxattr(dentry, name, fh->buf, fh->fb.len); err = ovl_do_setxattr(ofs, dentry, name, fh->buf, fh->fb.len);
if (err) if (err)
goto fail; goto fail;
...@@ -481,7 +484,7 @@ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index) ...@@ -481,7 +484,7 @@ struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index)
if (!d_is_dir(index)) if (!d_is_dir(index))
return dget(index); return dget(index);
fh = ovl_get_fh(index, OVL_XATTR_UPPER); fh = ovl_get_fh(ofs, index, OVL_XATTR_UPPER);
if (IS_ERR_OR_NULL(fh)) if (IS_ERR_OR_NULL(fh))
return ERR_CAST(fh); return ERR_CAST(fh);
...@@ -574,7 +577,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index) ...@@ -574,7 +577,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index)
goto fail; goto fail;
} }
err = ovl_verify_fh(upper, OVL_XATTR_ORIGIN, fh); err = ovl_verify_fh(ofs, upper, OVL_XATTR_ORIGIN, fh);
dput(upper); dput(upper);
if (err) if (err)
goto fail; goto fail;
...@@ -585,7 +588,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index) ...@@ -585,7 +588,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index)
if (err) if (err)
goto fail; goto fail;
if (ovl_get_nlink(origin.dentry, index, 0) == 0) if (ovl_get_nlink(ofs, origin.dentry, index, 0) == 0)
goto orphan; goto orphan;
} }
...@@ -741,7 +744,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper, ...@@ -741,7 +744,7 @@ struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
} }
/* Verify that dir index 'upper' xattr points to upper dir */ /* Verify that dir index 'upper' xattr points to upper dir */
err = ovl_verify_upper(index, upper, false); err = ovl_verify_upper(ofs, index, upper, false);
if (err) { if (err) {
if (err == -ESTALE) { if (err == -ESTALE) {
pr_warn_ratelimited("suspected multiply redirected dir found (upper=%pd2, origin=%pd2, index=%pd2).\n", pr_warn_ratelimited("suspected multiply redirected dir found (upper=%pd2, origin=%pd2, index=%pd2).\n",
...@@ -790,12 +793,12 @@ int ovl_path_next(int idx, struct dentry *dentry, struct path *path) ...@@ -790,12 +793,12 @@ int ovl_path_next(int idx, struct dentry *dentry, struct path *path)
} }
/* Fix missing 'origin' xattr */ /* Fix missing 'origin' xattr */
static int ovl_fix_origin(struct dentry *dentry, struct dentry *lower, static int ovl_fix_origin(struct ovl_fs *ofs, struct dentry *dentry,
struct dentry *upper) struct dentry *lower, struct dentry *upper)
{ {
int err; int err;
if (ovl_check_origin_xattr(upper)) if (ovl_check_origin_xattr(ofs, upper))
return 0; return 0;
err = ovl_want_write(dentry); err = ovl_want_write(dentry);
...@@ -920,7 +923,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ...@@ -920,7 +923,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
* of lower dir and set upper parent "impure". * of lower dir and set upper parent "impure".
*/ */
if (upperdentry && !ctr && !ofs->noxattr && d.is_dir) { if (upperdentry && !ctr && !ofs->noxattr && d.is_dir) {
err = ovl_fix_origin(dentry, this, upperdentry); err = ovl_fix_origin(ofs, dentry, this, upperdentry);
if (err) { if (err) {
dput(this); dput(this);
goto out_put; goto out_put;
...@@ -939,7 +942,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ...@@ -939,7 +942,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
if (upperdentry && !ctr && if (upperdentry && !ctr &&
((d.is_dir && ovl_verify_lower(dentry->d_sb)) || ((d.is_dir && ovl_verify_lower(dentry->d_sb)) ||
(!d.is_dir && ofs->config.index && origin_path))) { (!d.is_dir && ofs->config.index && origin_path))) {
err = ovl_verify_origin(upperdentry, this, false); err = ovl_verify_origin(ofs, upperdentry, this, false);
if (err) { if (err) {
dput(this); dput(this);
if (d.is_dir) if (d.is_dir)
...@@ -1060,13 +1063,13 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ...@@ -1060,13 +1063,13 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
ovl_dentry_set_upper_alias(dentry); ovl_dentry_set_upper_alias(dentry);
else if (index) { else if (index) {
upperdentry = dget(index); upperdentry = dget(index);
upperredirect = ovl_get_redirect_xattr(upperdentry, 0); upperredirect = ovl_get_redirect_xattr(ofs, upperdentry, 0);
if (IS_ERR(upperredirect)) { if (IS_ERR(upperredirect)) {
err = PTR_ERR(upperredirect); err = PTR_ERR(upperredirect);
upperredirect = NULL; upperredirect = NULL;
goto out_free_oe; goto out_free_oe;
} }
err = ovl_check_metacopy_xattr(upperdentry); err = ovl_check_metacopy_xattr(ofs, upperdentry);
if (err < 0) if (err < 0)
goto out_free_oe; goto out_free_oe;
uppermetacopy = err; uppermetacopy = err;
......
...@@ -170,14 +170,16 @@ static inline int ovl_do_symlink(struct inode *dir, struct dentry *dentry, ...@@ -170,14 +170,16 @@ static inline int ovl_do_symlink(struct inode *dir, struct dentry *dentry,
return err; return err;
} }
static inline ssize_t ovl_do_getxattr(struct dentry *dentry, const char *name, static inline ssize_t ovl_do_getxattr(struct ovl_fs *ofs, struct dentry *dentry,
void *value, size_t size) const char *name, void *value,
size_t size)
{ {
return vfs_getxattr(dentry, name, value, size); return vfs_getxattr(dentry, name, value, size);
} }
static inline int ovl_do_setxattr(struct dentry *dentry, const char *name, static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
const void *value, size_t size) const char *name, const void *value,
size_t size)
{ {
int err = vfs_setxattr(dentry, name, value, size, 0); int err = vfs_setxattr(dentry, name, value, size, 0);
pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n", pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n",
...@@ -185,7 +187,8 @@ static inline int ovl_do_setxattr(struct dentry *dentry, const char *name, ...@@ -185,7 +187,8 @@ static inline int ovl_do_setxattr(struct dentry *dentry, const char *name,
return err; return err;
} }
static inline int ovl_do_removexattr(struct dentry *dentry, const char *name) static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *dentry,
const char *name)
{ {
int err = vfs_removexattr(dentry, name); int err = vfs_removexattr(dentry, name);
pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err); pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err);
...@@ -286,8 +289,9 @@ struct file *ovl_path_open(struct path *path, int flags); ...@@ -286,8 +289,9 @@ struct file *ovl_path_open(struct path *path, int flags);
int ovl_copy_up_start(struct dentry *dentry, int flags); int ovl_copy_up_start(struct dentry *dentry, int flags);
void ovl_copy_up_end(struct dentry *dentry); void ovl_copy_up_end(struct dentry *dentry);
bool ovl_already_copied_up(struct dentry *dentry, int flags); bool ovl_already_copied_up(struct dentry *dentry, int flags);
bool ovl_check_origin_xattr(struct dentry *dentry); bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry);
bool ovl_check_dir_xattr(struct dentry *dentry, const char *name); bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry,
const char *name);
int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
const char *name, const void *value, size_t size, const char *name, const void *value, size_t size,
int xerr); int xerr);
...@@ -302,13 +306,15 @@ bool ovl_need_index(struct dentry *dentry); ...@@ -302,13 +306,15 @@ bool ovl_need_index(struct dentry *dentry);
int ovl_nlink_start(struct dentry *dentry); int ovl_nlink_start(struct dentry *dentry);
void ovl_nlink_end(struct dentry *dentry); void ovl_nlink_end(struct dentry *dentry);
int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir); int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
int ovl_check_metacopy_xattr(struct dentry *dentry); int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry);
bool ovl_is_metacopy_dentry(struct dentry *dentry); bool ovl_is_metacopy_dentry(struct dentry *dentry);
char *ovl_get_redirect_xattr(struct dentry *dentry, int padding); char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry,
int padding);
static inline bool ovl_is_impuredir(struct dentry *dentry) static inline bool ovl_is_impuredir(struct super_block *sb,
struct dentry *dentry)
{ {
return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE); return ovl_check_dir_xattr(sb, dentry, OVL_XATTR_IMPURE);
} }
/* /*
...@@ -369,8 +375,9 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt, ...@@ -369,8 +375,9 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
bool connected); bool connected);
int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected, int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
struct dentry *upperdentry, struct ovl_path **stackp); struct dentry *upperdentry, struct ovl_path **stackp);
int ovl_verify_set_fh(struct dentry *dentry, const char *name, int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry,
struct dentry *real, bool is_upper, bool set); const char *name, struct dentry *real, bool is_upper,
bool set);
struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index); struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index);
int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index); int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index);
int ovl_get_index_name(struct dentry *origin, struct qstr *name); int ovl_get_index_name(struct dentry *origin, struct qstr *name);
...@@ -382,16 +389,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ...@@ -382,16 +389,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags); unsigned int flags);
bool ovl_lower_positive(struct dentry *dentry); bool ovl_lower_positive(struct dentry *dentry);
static inline int ovl_verify_origin(struct dentry *upper, static inline int ovl_verify_origin(struct ovl_fs *ofs, struct dentry *upper,
struct dentry *origin, bool set) struct dentry *origin, bool set)
{ {
return ovl_verify_set_fh(upper, OVL_XATTR_ORIGIN, origin, false, set); return ovl_verify_set_fh(ofs, upper, OVL_XATTR_ORIGIN, origin,
false, set);
} }
static inline int ovl_verify_upper(struct dentry *index, static inline int ovl_verify_upper(struct ovl_fs *ofs, struct dentry *index,
struct dentry *upper, bool set) struct dentry *upper, bool set)
{ {
return ovl_verify_set_fh(index, OVL_XATTR_UPPER, upper, true, set); return ovl_verify_set_fh(ofs, index, OVL_XATTR_UPPER, upper, true, set);
} }
/* readdir.c */ /* readdir.c */
...@@ -408,7 +416,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs); ...@@ -408,7 +416,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs);
/* inode.c */ /* inode.c */
int ovl_set_nlink_upper(struct dentry *dentry); int ovl_set_nlink_upper(struct dentry *dentry);
int ovl_set_nlink_lower(struct dentry *dentry); int ovl_set_nlink_lower(struct dentry *dentry);
unsigned int ovl_get_nlink(struct dentry *lowerdentry, unsigned int ovl_get_nlink(struct ovl_fs *ofs, struct dentry *lowerdentry,
struct dentry *upperdentry, struct dentry *upperdentry,
unsigned int fallback); unsigned int fallback);
int ovl_setattr(struct dentry *dentry, struct iattr *attr); int ovl_setattr(struct dentry *dentry, struct iattr *attr);
...@@ -422,7 +430,7 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, ...@@ -422,7 +430,7 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
struct posix_acl *ovl_get_acl(struct inode *inode, int type); struct posix_acl *ovl_get_acl(struct inode *inode, int type);
int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags); int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags);
bool ovl_is_private_xattr(const char *name); bool ovl_is_private_xattr(struct super_block *sb, const char *name);
struct ovl_inode_params { struct ovl_inode_params {
struct inode *newinode; struct inode *newinode;
...@@ -488,7 +496,8 @@ void ovl_aio_request_cache_destroy(void); ...@@ -488,7 +496,8 @@ void ovl_aio_request_cache_destroy(void);
int ovl_copy_up(struct dentry *dentry); int ovl_copy_up(struct dentry *dentry);
int ovl_copy_up_with_data(struct dentry *dentry); int ovl_copy_up_with_data(struct dentry *dentry);
int ovl_maybe_copy_up(struct dentry *dentry, int flags); int ovl_maybe_copy_up(struct dentry *dentry, int flags);
int ovl_copy_xattr(struct dentry *old, struct dentry *new); int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
struct dentry *new);
int ovl_set_attr(struct dentry *upper, struct kstat *stat); int ovl_set_attr(struct dentry *upper, struct kstat *stat);
struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper); struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper);
int ovl_set_origin(struct dentry *dentry, struct dentry *lower, int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
......
...@@ -606,6 +606,7 @@ static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path) ...@@ -606,6 +606,7 @@ static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path)
{ {
int res; int res;
struct dentry *dentry = path->dentry; struct dentry *dentry = path->dentry;
struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
struct ovl_dir_cache *cache; struct ovl_dir_cache *cache;
cache = ovl_dir_cache(d_inode(dentry)); cache = ovl_dir_cache(d_inode(dentry));
...@@ -632,7 +633,7 @@ static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path) ...@@ -632,7 +633,7 @@ static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path)
* Removing the "impure" xattr is best effort. * Removing the "impure" xattr is best effort.
*/ */
if (!ovl_want_write(dentry)) { if (!ovl_want_write(dentry)) {
ovl_do_removexattr(ovl_dentry_upper(dentry), ovl_do_removexattr(ofs, ovl_dentry_upper(dentry),
OVL_XATTR_IMPURE); OVL_XATTR_IMPURE);
ovl_drop_write(dentry); ovl_drop_write(dentry);
} }
......
...@@ -1319,7 +1319,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, ...@@ -1319,7 +1319,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
/* /*
* Check if upper/work fs supports trusted.overlay.* xattr * Check if upper/work fs supports trusted.overlay.* xattr
*/ */
err = ovl_do_setxattr(ofs->workdir, OVL_XATTR_OPAQUE, "0", 1); err = ovl_do_setxattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE, "0", 1);
if (err) { if (err) {
ofs->noxattr = true; ofs->noxattr = true;
ofs->config.index = false; ofs->config.index = false;
...@@ -1327,7 +1327,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, ...@@ -1327,7 +1327,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
pr_warn("upper fs does not support xattr, falling back to index=off and metacopy=off.\n"); pr_warn("upper fs does not support xattr, falling back to index=off and metacopy=off.\n");
err = 0; err = 0;
} else { } else {
ovl_do_removexattr(ofs->workdir, OVL_XATTR_OPAQUE); ovl_do_removexattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE);
} }
/* /*
...@@ -1430,8 +1430,8 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, ...@@ -1430,8 +1430,8 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
return err; return err;
/* Verify lower root is upper root origin */ /* Verify lower root is upper root origin */
err = ovl_verify_origin(upperpath->dentry, oe->lowerstack[0].dentry, err = ovl_verify_origin(ofs, upperpath->dentry,
true); oe->lowerstack[0].dentry, true);
if (err) { if (err) {
pr_err("failed to verify upper root origin\n"); pr_err("failed to verify upper root origin\n");
goto out; goto out;
...@@ -1462,13 +1462,15 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs, ...@@ -1462,13 +1462,15 @@ static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
* "trusted.overlay.upper" to indicate that index may have * "trusted.overlay.upper" to indicate that index may have
* directory entries. * directory entries.
*/ */
if (ovl_check_origin_xattr(ofs->indexdir)) { if (ovl_check_origin_xattr(ofs, ofs->indexdir)) {
err = ovl_verify_set_fh(ofs->indexdir, OVL_XATTR_ORIGIN, err = ovl_verify_set_fh(ofs, ofs->indexdir,
OVL_XATTR_ORIGIN,
upperpath->dentry, true, false); upperpath->dentry, true, false);
if (err) if (err)
pr_err("failed to verify index dir 'origin' xattr\n"); pr_err("failed to verify index dir 'origin' xattr\n");
} }
err = ovl_verify_upper(ofs->indexdir, upperpath->dentry, true); err = ovl_verify_upper(ofs, ofs->indexdir, upperpath->dentry,
true);
if (err) if (err)
pr_err("failed to verify index dir 'upper' xattr\n"); pr_err("failed to verify index dir 'upper' xattr\n");
...@@ -1834,7 +1836,7 @@ static struct dentry *ovl_get_root(struct super_block *sb, ...@@ -1834,7 +1836,7 @@ static struct dentry *ovl_get_root(struct super_block *sb,
ino = d_inode(upperdentry)->i_ino; ino = d_inode(upperdentry)->i_ino;
fsid = 0; fsid = 0;
ovl_dentry_set_upper_alias(root); ovl_dentry_set_upper_alias(root);
if (ovl_is_impuredir(upperdentry)) if (ovl_is_impuredir(sb, upperdentry))
ovl_set_flag(OVL_IMPURE, d_inode(root)); ovl_set_flag(OVL_IMPURE, d_inode(root));
} }
......
...@@ -544,11 +544,11 @@ void ovl_copy_up_end(struct dentry *dentry) ...@@ -544,11 +544,11 @@ void ovl_copy_up_end(struct dentry *dentry)
ovl_inode_unlock(d_inode(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; int res;
res = ovl_do_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" */ /* Zero size value means "copied up but origin unknown" */
if (res >= 0) if (res >= 0)
...@@ -557,7 +557,8 @@ bool ovl_check_origin_xattr(struct dentry *dentry) ...@@ -557,7 +557,8 @@ bool ovl_check_origin_xattr(struct dentry *dentry)
return false; 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,
const char *name)
{ {
int res; int res;
char val; char val;
...@@ -565,7 +566,7 @@ bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) ...@@ -565,7 +566,7 @@ bool ovl_check_dir_xattr(struct dentry *dentry, const char *name)
if (!d_is_dir(dentry)) if (!d_is_dir(dentry))
return false; return false;
res = ovl_do_getxattr(dentry, name, &val, 1); res = ovl_do_getxattr(OVL_FS(sb), dentry, name, &val, 1);
if (res == 1 && val == 'y') if (res == 1 && val == 'y')
return true; return true;
...@@ -582,7 +583,7 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, ...@@ -582,7 +583,7 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
if (ofs->noxattr) if (ofs->noxattr)
return xerr; return xerr;
err = ovl_do_setxattr(upperdentry, name, value, size); err = ovl_do_setxattr(ofs, upperdentry, name, value, size);
if (err == -EOPNOTSUPP) { if (err == -EOPNOTSUPP) {
pr_warn("cannot set %s xattr on upper\n", name); pr_warn("cannot set %s xattr on upper\n", name);
...@@ -845,7 +846,7 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir) ...@@ -845,7 +846,7 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir)
} }
/* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */ /* 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; int res;
...@@ -853,7 +854,7 @@ int ovl_check_metacopy_xattr(struct dentry *dentry) ...@@ -853,7 +854,7 @@ int ovl_check_metacopy_xattr(struct dentry *dentry)
if (!S_ISREG(d_inode(dentry)->i_mode)) if (!S_ISREG(d_inode(dentry)->i_mode))
return 0; return 0;
res = ovl_do_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0); res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0);
if (res < 0) { if (res < 0) {
if (res == -ENODATA || res == -EOPNOTSUPP) if (res == -ENODATA || res == -EOPNOTSUPP)
return 0; return 0;
...@@ -882,12 +883,13 @@ bool ovl_is_metacopy_dentry(struct dentry *dentry) ...@@ -882,12 +883,13 @@ bool ovl_is_metacopy_dentry(struct dentry *dentry)
return (oe->numlower > 1); return (oe->numlower > 1);
} }
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; int res;
char *s, *next, *buf = NULL; char *s, *next, *buf = NULL;
res = ovl_do_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0); res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0);
if (res == -ENODATA || res == -EOPNOTSUPP) if (res == -ENODATA || res == -EOPNOTSUPP)
return NULL; return NULL;
if (res < 0) if (res < 0)
...@@ -899,7 +901,7 @@ char *ovl_get_redirect_xattr(struct dentry *dentry, int padding) ...@@ -899,7 +901,7 @@ char *ovl_get_redirect_xattr(struct dentry *dentry, int padding)
if (!buf) if (!buf)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
res = ovl_do_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res); res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res);
if (res < 0) if (res < 0)
goto fail; goto fail;
if (res == 0) if (res == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment