Skip to content

Commit dad7017

Browse files
braunerMiklos Szeredi
authored andcommitted
ovl: use ovl_path_getxattr() wrapper
Add a helper that allows to retrieve ovl xattrs from either lower or upper layers. To stop passing mnt and dentry separately everywhere use struct path which more accurately reflects the tight coupling between mount and dentry in this helper. Swich over all places to pass a path argument that can operate on either upper or lower layers. This is needed to support idmapped base layers with overlayfs. Some helpers are always called with an upper dentry, which is now utilized by these helpers to create the path. Make this usage explicit by renaming the argument to "upperdentry" and by renaming the function as well in some cases. Also add a check in ovl_do_getxattr() to catch misuse of these functions. Cc: <linux-unionfs@vger.kernel.org> Tested-by: Giuseppe Scrivano <gscrivan@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1 parent 22f289c commit dad7017

6 files changed

Lines changed: 111 additions & 65 deletions

File tree

fs/overlayfs/copy_up.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ static bool ovl_must_copy_xattr(const char *name)
4444
!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN);
4545
}
4646

47-
int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
48-
struct dentry *new)
47+
int ovl_copy_xattr(struct super_block *sb, struct path *oldpath, struct dentry *new)
4948
{
49+
struct dentry *old = oldpath->dentry;
5050
ssize_t list_size, size, value_size = 0;
5151
char *buf, *name, *value = NULL;
5252
int error = 0;
@@ -94,9 +94,9 @@ int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
9494
continue; /* Discard */
9595
}
9696
retry:
97-
size = vfs_getxattr(&init_user_ns, old, name, value, value_size);
97+
size = ovl_do_getxattr(oldpath, name, value, value_size);
9898
if (size == -ERANGE)
99-
size = vfs_getxattr(&init_user_ns, old, name, NULL, 0);
99+
size = ovl_do_getxattr(oldpath, name, NULL, 0);
100100

101101
if (size < 0) {
102102
error = size;
@@ -582,7 +582,7 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
582582
return err;
583583
}
584584

585-
err = ovl_copy_xattr(c->dentry->d_sb, c->lowerpath.dentry, temp);
585+
err = ovl_copy_xattr(c->dentry->d_sb, &c->lowerpath, temp);
586586
if (err)
587587
return err;
588588

@@ -873,13 +873,12 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode,
873873
return true;
874874
}
875875

876-
static ssize_t ovl_getxattr_value(struct ovl_fs *ofs, struct dentry *dentry,
877-
char *name, char **value)
876+
static ssize_t ovl_getxattr_value(struct path *path, char *name, char **value)
878877
{
879878
ssize_t res;
880879
char *buf;
881880

882-
res = ovl_do_getxattr(ofs, dentry, name, NULL, 0);
881+
res = ovl_do_getxattr(path, name, NULL, 0);
883882
if (res == -ENODATA || res == -EOPNOTSUPP)
884883
res = 0;
885884

@@ -888,7 +887,7 @@ static ssize_t ovl_getxattr_value(struct ovl_fs *ofs, struct dentry *dentry,
888887
if (!buf)
889888
return -ENOMEM;
890889

891-
res = ovl_do_getxattr(ofs, dentry, name, buf, res);
890+
res = ovl_do_getxattr(path, name, buf, res);
892891
if (res < 0)
893892
kfree(buf);
894893
else
@@ -915,8 +914,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
915914
return -EIO;
916915

917916
if (c->stat.size) {
918-
err = cap_size = ovl_getxattr_value(ofs, upperpath.dentry,
919-
XATTR_NAME_CAPS, &capability);
917+
err = cap_size = ovl_getxattr_value(&upperpath, XATTR_NAME_CAPS,
918+
&capability);
920919
if (cap_size < 0)
921920
goto out;
922921
}

fs/overlayfs/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
398398
if (IS_ERR(opaquedir))
399399
goto out_unlock;
400400

401-
err = ovl_copy_xattr(dentry->d_sb, upper, opaquedir);
401+
err = ovl_copy_xattr(dentry->d_sb, &upperpath, opaquedir);
402402
if (err)
403403
goto out_cleanup;
404404

fs/overlayfs/inode.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -899,8 +899,8 @@ unsigned int ovl_get_nlink(struct ovl_fs *ofs, struct dentry *lowerdentry,
899899
if (!lowerdentry || !upperdentry || d_inode(lowerdentry)->i_nlink == 1)
900900
return fallback;
901901

902-
err = ovl_getxattr(ofs, upperdentry, OVL_XATTR_NLINK,
903-
&buf, sizeof(buf) - 1);
902+
err = ovl_getxattr_upper(ofs, upperdentry, OVL_XATTR_NLINK,
903+
&buf, sizeof(buf) - 1);
904904
if (err < 0)
905905
goto fail;
906906

@@ -1104,6 +1104,10 @@ struct inode *ovl_get_inode(struct super_block *sb,
11041104
struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL;
11051105
struct inode *inode;
11061106
struct dentry *lowerdentry = lowerpath ? lowerpath->dentry : NULL;
1107+
struct path realpath = {
1108+
.dentry = upperdentry ?: lowerdentry,
1109+
.mnt = upperdentry ? ovl_upper_mnt(ofs) : lowerpath->layer->mnt,
1110+
};
11071111
bool bylower = ovl_hash_bylower(sb, upperdentry, lowerdentry,
11081112
oip->index);
11091113
int fsid = bylower ? lowerpath->layer->fsid : 0;
@@ -1177,7 +1181,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
11771181
/* Check for non-merge dir that may have whiteouts */
11781182
if (is_dir) {
11791183
if (((upperdentry && lowerdentry) || oip->numlower > 1) ||
1180-
ovl_check_origin_xattr(ofs, upperdentry ?: lowerdentry)) {
1184+
ovl_path_check_origin_xattr(ofs, &realpath)) {
11811185
ovl_set_flag(OVL_WHITEOUTS, inode);
11821186
}
11831187
}

fs/overlayfs/namei.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
struct ovl_lookup_data {
1818
struct super_block *sb;
19+
struct vfsmount *mnt;
1920
struct qstr name;
2021
bool is_dir;
2122
bool opaque;
@@ -25,14 +26,14 @@ struct ovl_lookup_data {
2526
bool metacopy;
2627
};
2728

28-
static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d,
29+
static int ovl_check_redirect(struct path *path, struct ovl_lookup_data *d,
2930
size_t prelen, const char *post)
3031
{
3132
int res;
3233
char *buf;
3334
struct ovl_fs *ofs = OVL_FS(d->sb);
3435

35-
buf = ovl_get_redirect_xattr(ofs, dentry, prelen + strlen(post));
36+
buf = ovl_get_redirect_xattr(ofs, path, prelen + strlen(post));
3637
if (IS_ERR_OR_NULL(buf))
3738
return PTR_ERR(buf);
3839

@@ -105,13 +106,13 @@ int ovl_check_fb_len(struct ovl_fb *fb, int fb_len)
105106
return 0;
106107
}
107108

108-
static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry,
109+
static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *upperdentry,
109110
enum ovl_xattr ox)
110111
{
111112
int res, err;
112113
struct ovl_fh *fh = NULL;
113114

114-
res = ovl_getxattr(ofs, dentry, ox, NULL, 0);
115+
res = ovl_getxattr_upper(ofs, upperdentry, ox, NULL, 0);
115116
if (res < 0) {
116117
if (res == -ENODATA || res == -EOPNOTSUPP)
117118
return NULL;
@@ -125,7 +126,7 @@ static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry,
125126
if (!fh)
126127
return ERR_PTR(-ENOMEM);
127128

128-
res = ovl_getxattr(ofs, dentry, ox, fh->buf, res);
129+
res = ovl_getxattr_upper(ofs, upperdentry, ox, fh->buf, res);
129130
if (res < 0)
130131
goto fail;
131132

@@ -193,9 +194,9 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
193194
return real;
194195
}
195196

196-
static bool ovl_is_opaquedir(struct super_block *sb, struct dentry *dentry)
197+
static bool ovl_is_opaquedir(struct ovl_fs *ofs, struct path *path)
197198
{
198-
return ovl_check_dir_xattr(sb, dentry, OVL_XATTR_OPAQUE);
199+
return ovl_path_check_dir_xattr(ofs, path, OVL_XATTR_OPAQUE);
199200
}
200201

201202
static struct dentry *ovl_lookup_positive_unlocked(const char *name,
@@ -224,6 +225,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
224225
struct dentry **ret, bool drop_negative)
225226
{
226227
struct dentry *this;
228+
struct path path;
227229
int err;
228230
bool last_element = !post[0];
229231

@@ -253,12 +255,15 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
253255
d->stop = true;
254256
goto put_and_out;
255257
}
258+
259+
path.dentry = this;
260+
path.mnt = d->mnt;
256261
if (!d_can_lookup(this)) {
257262
if (d->is_dir || !last_element) {
258263
d->stop = true;
259264
goto put_and_out;
260265
}
261-
err = ovl_check_metacopy_xattr(OVL_FS(d->sb), this);
266+
err = ovl_check_metacopy_xattr(OVL_FS(d->sb), &path);
262267
if (err < 0)
263268
goto out_err;
264269

@@ -278,14 +283,14 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
278283
if (d->last)
279284
goto out;
280285

281-
if (ovl_is_opaquedir(d->sb, this)) {
286+
if (ovl_is_opaquedir(OVL_FS(d->sb), &path)) {
282287
d->stop = true;
283288
if (last_element)
284289
d->opaque = true;
285290
goto out;
286291
}
287292
}
288-
err = ovl_check_redirect(this, d, prelen, post);
293+
err = ovl_check_redirect(&path, d, prelen, post);
289294
if (err)
290295
goto out_err;
291296
out:
@@ -856,6 +861,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
856861
old_cred = ovl_override_creds(dentry->d_sb);
857862
upperdir = ovl_dentry_upper(dentry->d_parent);
858863
if (upperdir) {
864+
d.mnt = ovl_upper_mnt(ofs);
859865
err = ovl_lookup_layer(upperdir, &d, &upperdentry, true);
860866
if (err)
861867
goto out;
@@ -911,6 +917,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
911917
else
912918
d.last = lower.layer->idx == roe->numlower;
913919

920+
d.mnt = lower.layer->mnt;
914921
err = ovl_lookup_layer(lower.dentry, &d, &this, false);
915922
if (err)
916923
goto out_put;
@@ -1071,14 +1078,18 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
10711078
if (upperdentry)
10721079
ovl_dentry_set_upper_alias(dentry);
10731080
else if (index) {
1074-
upperdentry = dget(index);
1075-
upperredirect = ovl_get_redirect_xattr(ofs, upperdentry, 0);
1081+
struct path upperpath = {
1082+
.dentry = upperdentry = dget(index),
1083+
.mnt = ovl_upper_mnt(ofs),
1084+
};
1085+
1086+
upperredirect = ovl_get_redirect_xattr(ofs, &upperpath, 0);
10761087
if (IS_ERR(upperredirect)) {
10771088
err = PTR_ERR(upperredirect);
10781089
upperredirect = NULL;
10791090
goto out_free_oe;
10801091
}
1081-
err = ovl_check_metacopy_xattr(ofs, upperdentry);
1092+
err = ovl_check_metacopy_xattr(ofs, &upperpath);
10821093
if (err < 0)
10831094
goto out_free_oe;
10841095
uppermetacopy = err;

fs/overlayfs/overlayfs.h

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -218,30 +218,48 @@ static inline int ovl_do_symlink(struct ovl_fs *ofs,
218218
return err;
219219
}
220220

221-
static inline ssize_t ovl_do_getxattr(struct ovl_fs *ofs, struct dentry *dentry,
222-
const char *name, void *value,
223-
size_t size)
221+
static inline ssize_t ovl_do_getxattr(struct path *path, const char *name,
222+
void *value, size_t size)
224223
{
225-
int err = vfs_getxattr(&init_user_ns, dentry, name, value, size);
226-
int len = (value && err > 0) ? err : 0;
224+
int err, len;
225+
226+
WARN_ON(path->dentry->d_sb != path->mnt->mnt_sb);
227+
228+
err = vfs_getxattr(mnt_user_ns(path->mnt), path->dentry,
229+
name, value, size);
230+
len = (value && err > 0) ? err : 0;
227231

228232
pr_debug("getxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n",
229-
dentry, name, min(len, 48), value, size, err);
233+
path->dentry, name, min(len, 48), value, size, err);
230234
return err;
231235
}
232236

233-
static inline ssize_t ovl_getxattr(struct ovl_fs *ofs, struct dentry *dentry,
234-
enum ovl_xattr ox, void *value,
235-
size_t size)
237+
static inline ssize_t ovl_getxattr_upper(struct ovl_fs *ofs,
238+
struct dentry *upperdentry,
239+
enum ovl_xattr ox, void *value,
240+
size_t size)
241+
{
242+
struct path upperpath = {
243+
.dentry = upperdentry,
244+
.mnt = ovl_upper_mnt(ofs),
245+
};
246+
247+
return ovl_do_getxattr(&upperpath, ovl_xattr(ofs, ox), value, size);
248+
}
249+
250+
static inline ssize_t ovl_path_getxattr(struct ovl_fs *ofs,
251+
struct path *path,
252+
enum ovl_xattr ox, void *value,
253+
size_t size)
236254
{
237-
return ovl_do_getxattr(ofs, dentry, ovl_xattr(ofs, ox), value, size);
255+
return ovl_do_getxattr(path, ovl_xattr(ofs, ox), value, size);
238256
}
239257

240258
static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
241259
const char *name, const void *value,
242260
size_t size, int flags)
243261
{
244-
int err = vfs_setxattr(&init_user_ns, dentry, name, value, size, flags);
262+
int err = vfs_setxattr(ovl_upper_mnt_userns(ofs), dentry, name, value, size, flags);
245263

246264
pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) = %i\n",
247265
dentry, name, min((int)size, 48), value, size, flags, err);
@@ -258,7 +276,7 @@ static inline int ovl_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
258276
static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *dentry,
259277
const char *name)
260278
{
261-
int err = vfs_removexattr(&init_user_ns, dentry, name);
279+
int err = vfs_removexattr(ovl_upper_mnt_userns(ofs), dentry, name);
262280
pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err);
263281
return err;
264282
}
@@ -394,9 +412,20 @@ struct file *ovl_path_open(struct path *path, int flags);
394412
int ovl_copy_up_start(struct dentry *dentry, int flags);
395413
void ovl_copy_up_end(struct dentry *dentry);
396414
bool ovl_already_copied_up(struct dentry *dentry, int flags);
397-
bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry);
398-
bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry,
399-
enum ovl_xattr ox);
415+
bool ovl_path_check_dir_xattr(struct ovl_fs *ofs, struct path *path,
416+
enum ovl_xattr ox);
417+
bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, struct path *path);
418+
419+
static inline bool ovl_check_origin_xattr(struct ovl_fs *ofs,
420+
struct dentry *upperdentry)
421+
{
422+
struct path upperpath = {
423+
.dentry = upperdentry,
424+
.mnt = ovl_upper_mnt(ofs),
425+
};
426+
return ovl_path_check_origin_xattr(ofs, &upperpath);
427+
}
428+
400429
int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry,
401430
enum ovl_xattr ox, const void *value, size_t size,
402431
int xerr);
@@ -408,10 +437,9 @@ bool ovl_need_index(struct dentry *dentry);
408437
int ovl_nlink_start(struct dentry *dentry);
409438
void ovl_nlink_end(struct dentry *dentry);
410439
int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
411-
int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry);
440+
int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct path *path);
412441
bool ovl_is_metacopy_dentry(struct dentry *dentry);
413-
char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry,
414-
int padding);
442+
char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct path *path, int padding);
415443
int ovl_sync_status(struct ovl_fs *ofs);
416444

417445
static inline void ovl_set_flag(unsigned long flag, struct inode *inode)
@@ -430,9 +458,15 @@ static inline bool ovl_test_flag(unsigned long flag, struct inode *inode)
430458
}
431459

432460
static inline bool ovl_is_impuredir(struct super_block *sb,
433-
struct dentry *dentry)
461+
struct dentry *upperdentry)
434462
{
435-
return ovl_check_dir_xattr(sb, dentry, OVL_XATTR_IMPURE);
463+
struct ovl_fs *ofs = OVL_FS(sb);
464+
struct path upperpath = {
465+
.dentry = upperdentry,
466+
.mnt = ovl_upper_mnt(ofs),
467+
};
468+
469+
return ovl_path_check_dir_xattr(ofs, &upperpath, OVL_XATTR_IMPURE);
436470
}
437471

438472
/*
@@ -659,8 +693,7 @@ int ovl_fileattr_set(struct user_namespace *mnt_userns,
659693
int ovl_copy_up(struct dentry *dentry);
660694
int ovl_copy_up_with_data(struct dentry *dentry);
661695
int ovl_maybe_copy_up(struct dentry *dentry, int flags);
662-
int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
663-
struct dentry *new);
696+
int ovl_copy_xattr(struct super_block *sb, struct path *path, struct dentry *new);
664697
int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat);
665698
struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
666699
bool is_upper);

0 commit comments

Comments
 (0)