Skip to content

Commit 2a8c810

Browse files
mihalicynMiklos Szeredi
authored andcommitted
fuse: support idmapped getattr inode op
We have to: - pass an idmapping to the generic_fillattr() to properly handle UIG/GID mapping for the userspace. - pass -/- to fuse_fillattr() (analog of generic_fillattr() in fuse). Difference between these two is that generic_fillattr() takes all the stat() data from the inode directly, while fuse_fillattr() codepath takes a fresh data just from the userspace reply on the FUSE_GETATTR request. In some cases we can just pass &nop_mnt_idmap, because idmapping won't be used in these codepaths. For example, when 3rd argument of fuse_do_getattr() is NULL then idmap argument is not used. Signed-off-by: Alexander Mikhalitsyn <[email protected]> Reviewed-by: Christian Brauner <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 556208e commit 2a8c810

File tree

1 file changed

+24
-20
lines changed

1 file changed

+24
-20
lines changed

fs/fuse/dir.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,18 +1135,22 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
11351135
return err;
11361136
}
11371137

1138-
static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
1139-
struct kstat *stat)
1138+
static void fuse_fillattr(struct mnt_idmap *idmap, struct inode *inode,
1139+
struct fuse_attr *attr, struct kstat *stat)
11401140
{
11411141
unsigned int blkbits;
11421142
struct fuse_conn *fc = get_fuse_conn(inode);
1143+
vfsuid_t vfsuid = make_vfsuid(idmap, fc->user_ns,
1144+
make_kuid(fc->user_ns, attr->uid));
1145+
vfsgid_t vfsgid = make_vfsgid(idmap, fc->user_ns,
1146+
make_kgid(fc->user_ns, attr->gid));
11431147

11441148
stat->dev = inode->i_sb->s_dev;
11451149
stat->ino = attr->ino;
11461150
stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
11471151
stat->nlink = attr->nlink;
1148-
stat->uid = make_kuid(fc->user_ns, attr->uid);
1149-
stat->gid = make_kgid(fc->user_ns, attr->gid);
1152+
stat->uid = vfsuid_into_kuid(vfsuid);
1153+
stat->gid = vfsgid_into_kgid(vfsgid);
11501154
stat->rdev = inode->i_rdev;
11511155
stat->atime.tv_sec = attr->atime;
11521156
stat->atime.tv_nsec = attr->atimensec;
@@ -1185,8 +1189,8 @@ static void fuse_statx_to_attr(struct fuse_statx *sx, struct fuse_attr *attr)
11851189
attr->blksize = sx->blksize;
11861190
}
11871191

1188-
static int fuse_do_statx(struct inode *inode, struct file *file,
1189-
struct kstat *stat)
1192+
static int fuse_do_statx(struct mnt_idmap *idmap, struct inode *inode,
1193+
struct file *file, struct kstat *stat)
11901194
{
11911195
int err;
11921196
struct fuse_attr attr;
@@ -1239,15 +1243,15 @@ static int fuse_do_statx(struct inode *inode, struct file *file,
12391243
stat->result_mask = sx->mask & (STATX_BASIC_STATS | STATX_BTIME);
12401244
stat->btime.tv_sec = sx->btime.tv_sec;
12411245
stat->btime.tv_nsec = min_t(u32, sx->btime.tv_nsec, NSEC_PER_SEC - 1);
1242-
fuse_fillattr(inode, &attr, stat);
1246+
fuse_fillattr(idmap, inode, &attr, stat);
12431247
stat->result_mask |= STATX_TYPE;
12441248
}
12451249

12461250
return 0;
12471251
}
12481252

1249-
static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
1250-
struct file *file)
1253+
static int fuse_do_getattr(struct mnt_idmap *idmap, struct inode *inode,
1254+
struct kstat *stat, struct file *file)
12511255
{
12521256
int err;
12531257
struct fuse_getattr_in inarg;
@@ -1286,15 +1290,15 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
12861290
ATTR_TIMEOUT(&outarg),
12871291
attr_version);
12881292
if (stat)
1289-
fuse_fillattr(inode, &outarg.attr, stat);
1293+
fuse_fillattr(idmap, inode, &outarg.attr, stat);
12901294
}
12911295
}
12921296
return err;
12931297
}
12941298

1295-
static int fuse_update_get_attr(struct inode *inode, struct file *file,
1296-
struct kstat *stat, u32 request_mask,
1297-
unsigned int flags)
1299+
static int fuse_update_get_attr(struct mnt_idmap *idmap, struct inode *inode,
1300+
struct file *file, struct kstat *stat,
1301+
u32 request_mask, unsigned int flags)
12981302
{
12991303
struct fuse_inode *fi = get_fuse_inode(inode);
13001304
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1325,17 +1329,17 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
13251329
forget_all_cached_acls(inode);
13261330
/* Try statx if BTIME is requested */
13271331
if (!fc->no_statx && (request_mask & ~STATX_BASIC_STATS)) {
1328-
err = fuse_do_statx(inode, file, stat);
1332+
err = fuse_do_statx(idmap, inode, file, stat);
13291333
if (err == -ENOSYS) {
13301334
fc->no_statx = 1;
13311335
err = 0;
13321336
goto retry;
13331337
}
13341338
} else {
1335-
err = fuse_do_getattr(inode, stat, file);
1339+
err = fuse_do_getattr(idmap, inode, stat, file);
13361340
}
13371341
} else if (stat) {
1338-
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
1342+
generic_fillattr(idmap, request_mask, inode, stat);
13391343
stat->mode = fi->orig_i_mode;
13401344
stat->ino = fi->orig_ino;
13411345
if (test_bit(FUSE_I_BTIME, &fi->state)) {
@@ -1349,7 +1353,7 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
13491353

13501354
int fuse_update_attributes(struct inode *inode, struct file *file, u32 mask)
13511355
{
1352-
return fuse_update_get_attr(inode, file, NULL, mask, 0);
1356+
return fuse_update_get_attr(&nop_mnt_idmap, inode, file, NULL, mask, 0);
13531357
}
13541358

13551359
int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
@@ -1493,7 +1497,7 @@ static int fuse_perm_getattr(struct inode *inode, int mask)
14931497
return -ECHILD;
14941498

14951499
forget_all_cached_acls(inode);
1496-
return fuse_do_getattr(inode, NULL, NULL);
1500+
return fuse_do_getattr(&nop_mnt_idmap, inode, NULL, NULL);
14971501
}
14981502

14991503
/*
@@ -2072,7 +2076,7 @@ static int fuse_setattr(struct mnt_idmap *idmap, struct dentry *entry,
20722076
* ia_mode calculation may have used stale i_mode.
20732077
* Refresh and recalculate.
20742078
*/
2075-
ret = fuse_do_getattr(inode, NULL, file);
2079+
ret = fuse_do_getattr(idmap, inode, NULL, file);
20762080
if (ret)
20772081
return ret;
20782082

@@ -2129,7 +2133,7 @@ static int fuse_getattr(struct mnt_idmap *idmap,
21292133
return -EACCES;
21302134
}
21312135

2132-
return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
2136+
return fuse_update_get_attr(idmap, inode, NULL, stat, request_mask, flags);
21332137
}
21342138

21352139
static const struct inode_operations fuse_dir_inode_operations = {

0 commit comments

Comments
 (0)