Skip to content

Commit 0d56a45

Browse files
author
Christian Brauner
committed
stat: handle idmapped mounts
The generic_fillattr() helper fills in the basic attributes associated with an inode. Enable it to handle idmapped mounts. If the inode is accessed through an idmapped mount map it into the mount's user namespace before we store the uid and gid. If the initial user namespace is passed nothing changes so non-idmapped mounts will see identical behavior as before. Link: https://lore.kernel.org/r/[email protected] Cc: Christoph Hellwig <[email protected]> Cc: David Howells <[email protected]> Cc: Al Viro <[email protected]> Cc: [email protected] Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: James Morris <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 71bc356 commit 0d56a45

File tree

36 files changed

+54
-46
lines changed

36 files changed

+54
-46
lines changed

fs/9p/vfs_inode.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,7 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
10271027
p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
10281028
v9ses = v9fs_dentry2v9ses(dentry);
10291029
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1030-
generic_fillattr(d_inode(dentry), stat);
1030+
generic_fillattr(&init_user_ns, d_inode(dentry), stat);
10311031
return 0;
10321032
}
10331033
fid = v9fs_fid_lookup(dentry);
@@ -1040,7 +1040,7 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
10401040
return PTR_ERR(st);
10411041

10421042
v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb, 0);
1043-
generic_fillattr(d_inode(dentry), stat);
1043+
generic_fillattr(&init_user_ns, d_inode(dentry), stat);
10441044

10451045
p9stat_free(st);
10461046
kfree(st);

fs/9p/vfs_inode_dotl.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ v9fs_vfs_getattr_dotl(const struct path *path, struct kstat *stat,
468468
p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
469469
v9ses = v9fs_dentry2v9ses(dentry);
470470
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
471-
generic_fillattr(d_inode(dentry), stat);
471+
generic_fillattr(&init_user_ns, d_inode(dentry), stat);
472472
return 0;
473473
}
474474
fid = v9fs_fid_lookup(dentry);
@@ -485,7 +485,7 @@ v9fs_vfs_getattr_dotl(const struct path *path, struct kstat *stat,
485485
return PTR_ERR(st);
486486

487487
v9fs_stat2inode_dotl(st, d_inode(dentry), 0);
488-
generic_fillattr(d_inode(dentry), stat);
488+
generic_fillattr(&init_user_ns, d_inode(dentry), stat);
489489
/* Change block size to what the server returned */
490490
stat->blksize = st->st_blksize;
491491

fs/afs/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ int afs_getattr(const struct path *path, struct kstat *stat,
745745

746746
do {
747747
read_seqbegin_or_lock(&vnode->cb_lock, &seq);
748-
generic_fillattr(inode, stat);
748+
generic_fillattr(&init_user_ns, inode, stat);
749749
if (test_bit(AFS_VNODE_SILLY_DELETED, &vnode->flags) &&
750750
stat->nlink > 0)
751751
stat->nlink -= 1;

fs/btrfs/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -8842,7 +8842,7 @@ static int btrfs_getattr(const struct path *path, struct kstat *stat,
88428842
STATX_ATTR_IMMUTABLE |
88438843
STATX_ATTR_NODUMP);
88448844

8845-
generic_fillattr(inode, stat);
8845+
generic_fillattr(&init_user_ns, inode, stat);
88468846
stat->dev = BTRFS_I(inode)->root->anon_dev;
88478847

88488848
spin_lock(&BTRFS_I(inode)->lock);

fs/ceph/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2385,7 +2385,7 @@ int ceph_getattr(const struct path *path, struct kstat *stat,
23852385
return err;
23862386
}
23872387

2388-
generic_fillattr(inode, stat);
2388+
generic_fillattr(&init_user_ns, inode, stat);
23892389
stat->ino = ceph_present_inode(inode);
23902390

23912391
/*

fs/cifs/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2408,7 +2408,7 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
24082408
return rc;
24092409
}
24102410

2411-
generic_fillattr(inode, stat);
2411+
generic_fillattr(&init_user_ns, inode, stat);
24122412
stat->blksize = cifs_sb->ctx->bsize;
24132413
stat->ino = CIFS_I(inode)->uniqueid;
24142414

fs/coda/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ int coda_getattr(const struct path *path, struct kstat *stat,
256256
{
257257
int err = coda_revalidate_inode(d_inode(path->dentry));
258258
if (!err)
259-
generic_fillattr(d_inode(path->dentry), stat);
259+
generic_fillattr(&init_user_ns, d_inode(path->dentry), stat);
260260
return err;
261261
}
262262

fs/ecryptfs/inode.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ static int ecryptfs_getattr_link(const struct path *path, struct kstat *stat,
977977

978978
mount_crypt_stat = &ecryptfs_superblock_to_private(
979979
dentry->d_sb)->mount_crypt_stat;
980-
generic_fillattr(d_inode(dentry), stat);
980+
generic_fillattr(&init_user_ns, d_inode(dentry), stat);
981981
if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
982982
char *target;
983983
size_t targetsiz;
@@ -1005,7 +1005,7 @@ static int ecryptfs_getattr(const struct path *path, struct kstat *stat,
10051005
if (!rc) {
10061006
fsstack_copy_attr_all(d_inode(dentry),
10071007
ecryptfs_inode_to_lower(d_inode(dentry)));
1008-
generic_fillattr(d_inode(dentry), stat);
1008+
generic_fillattr(&init_user_ns, d_inode(dentry), stat);
10091009
stat->blocks = lower_stat.blocks;
10101010
}
10111011
return rc;

fs/erofs/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ int erofs_getattr(const struct path *path, struct kstat *stat,
343343
stat->attributes_mask |= (STATX_ATTR_COMPRESSED |
344344
STATX_ATTR_IMMUTABLE);
345345

346-
generic_fillattr(inode, stat);
346+
generic_fillattr(&init_user_ns, inode, stat);
347347
return 0;
348348
}
349349

fs/exfat/file.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ int exfat_getattr(const struct path *path, struct kstat *stat,
273273
struct inode *inode = d_backing_inode(path->dentry);
274274
struct exfat_inode_info *ei = EXFAT_I(inode);
275275

276-
generic_fillattr(inode, stat);
276+
generic_fillattr(&init_user_ns, inode, stat);
277277
exfat_truncate_atime(&stat->atime);
278278
stat->result_mask |= STATX_BTIME;
279279
stat->btime.tv_sec = ei->i_crtime.tv_sec;

fs/ext2/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1660,7 +1660,7 @@ int ext2_getattr(const struct path *path, struct kstat *stat,
16601660
STATX_ATTR_IMMUTABLE |
16611661
STATX_ATTR_NODUMP);
16621662

1663-
generic_fillattr(inode, stat);
1663+
generic_fillattr(&init_user_ns, inode, stat);
16641664
return 0;
16651665
}
16661666

fs/ext4/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5571,7 +5571,7 @@ int ext4_getattr(const struct path *path, struct kstat *stat,
55715571
STATX_ATTR_NODUMP |
55725572
STATX_ATTR_VERITY);
55735573

5574-
generic_fillattr(inode, stat);
5574+
generic_fillattr(&init_user_ns, inode, stat);
55755575
return 0;
55765576
}
55775577

fs/f2fs/file.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
820820
STATX_ATTR_NODUMP |
821821
STATX_ATTR_VERITY);
822822

823-
generic_fillattr(inode, stat);
823+
generic_fillattr(&init_user_ns, inode, stat);
824824

825825
/* we need to show initial sectors used for inline_data/dentries */
826826
if ((S_ISREG(inode->i_mode) && f2fs_has_inline_data(inode)) ||

fs/fat/file.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ int fat_getattr(const struct path *path, struct kstat *stat,
398398
u32 request_mask, unsigned int flags)
399399
{
400400
struct inode *inode = d_inode(path->dentry);
401-
generic_fillattr(inode, stat);
401+
generic_fillattr(&init_user_ns, inode, stat);
402402
stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size;
403403

404404
if (MSDOS_SB(inode->i_sb)->options.nfs == FAT_NFS_NOSTALE_RO) {

fs/fuse/dir.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,7 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
10871087
forget_all_cached_acls(inode);
10881088
err = fuse_do_getattr(inode, stat, file);
10891089
} else if (stat) {
1090-
generic_fillattr(inode, stat);
1090+
generic_fillattr(&init_user_ns, inode, stat);
10911091
stat->mode = fi->orig_i_mode;
10921092
stat->ino = fi->orig_ino;
10931093
}

fs/gfs2/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2050,7 +2050,7 @@ static int gfs2_getattr(const struct path *path, struct kstat *stat,
20502050
STATX_ATTR_IMMUTABLE |
20512051
STATX_ATTR_NODUMP);
20522052

2053-
generic_fillattr(inode, stat);
2053+
generic_fillattr(&init_user_ns, inode, stat);
20542054

20552055
if (gfs2_holder_initialized(&gh))
20562056
gfs2_glock_dq_uninit(&gh);

fs/hfsplus/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ int hfsplus_getattr(const struct path *path, struct kstat *stat,
286286
stat->attributes_mask |= STATX_ATTR_APPEND | STATX_ATTR_IMMUTABLE |
287287
STATX_ATTR_NODUMP;
288288

289-
generic_fillattr(inode, stat);
289+
generic_fillattr(&init_user_ns, inode, stat);
290290
return 0;
291291
}
292292

fs/kernfs/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
193193
kernfs_refresh_inode(kn, inode);
194194
mutex_unlock(&kernfs_mutex);
195195

196-
generic_fillattr(inode, stat);
196+
generic_fillattr(&init_user_ns, inode, stat);
197197
return 0;
198198
}
199199

fs/libfs.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ int simple_getattr(const struct path *path, struct kstat *stat,
3131
u32 request_mask, unsigned int query_flags)
3232
{
3333
struct inode *inode = d_inode(path->dentry);
34-
generic_fillattr(inode, stat);
34+
generic_fillattr(&init_user_ns, inode, stat);
3535
stat->blocks = inode->i_mapping->nrpages << (PAGE_SHIFT - 9);
3636
return 0;
3737
}
@@ -1304,7 +1304,7 @@ static int empty_dir_getattr(const struct path *path, struct kstat *stat,
13041304
u32 request_mask, unsigned int query_flags)
13051305
{
13061306
struct inode *inode = d_inode(path->dentry);
1307-
generic_fillattr(inode, stat);
1307+
generic_fillattr(&init_user_ns, inode, stat);
13081308
return 0;
13091309
}
13101310

fs/minix/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ int minix_getattr(const struct path *path, struct kstat *stat,
658658
struct super_block *sb = path->dentry->d_sb;
659659
struct inode *inode = d_inode(path->dentry);
660660

661-
generic_fillattr(inode, stat);
661+
generic_fillattr(&init_user_ns, inode, stat);
662662
if (INODE_VERSION(inode) == MINIX_V1)
663663
stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
664664
else

fs/nfs/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,7 @@ int nfs_getattr(const struct path *path, struct kstat *stat,
857857
/* Only return attributes that were revalidated. */
858858
stat->result_mask &= request_mask;
859859
out_no_update:
860-
generic_fillattr(inode, stat);
860+
generic_fillattr(&init_user_ns, inode, stat);
861861
stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));
862862
if (S_ISDIR(inode->i_mode))
863863
stat->blksize = NFS_SERVER(inode)->dtsize;

fs/nfs/namespace.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ nfs_namespace_getattr(const struct path *path, struct kstat *stat,
213213
{
214214
if (NFS_FH(d_inode(path->dentry))->size != 0)
215215
return nfs_getattr(path, stat, request_mask, query_flags);
216-
generic_fillattr(d_inode(path->dentry), stat);
216+
generic_fillattr(&init_user_ns, d_inode(path->dentry), stat);
217217
return 0;
218218
}
219219

fs/ocfs2/file.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1313,7 +1313,7 @@ int ocfs2_getattr(const struct path *path, struct kstat *stat,
13131313
goto bail;
13141314
}
13151315

1316-
generic_fillattr(inode, stat);
1316+
generic_fillattr(&init_user_ns, inode, stat);
13171317
/*
13181318
* If there is inline data in the inode, the inode will normally not
13191319
* have data blocks allocated (it may have an external xattr block).

fs/orangefs/inode.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
903903
ret = orangefs_inode_getattr(inode,
904904
request_mask & STATX_SIZE ? ORANGEFS_GETATTR_SIZE : 0);
905905
if (ret == 0) {
906-
generic_fillattr(inode, stat);
906+
generic_fillattr(&init_user_ns, inode, stat);
907907

908908
/* override block size reported to stat */
909909
if (!(request_mask & STATX_SIZE))

fs/proc/base.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,7 @@ int pid_getattr(const struct path *path, struct kstat *stat,
19341934
struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
19351935
struct task_struct *task;
19361936

1937-
generic_fillattr(inode, stat);
1937+
generic_fillattr(&init_user_ns, inode, stat);
19381938

19391939
stat->uid = GLOBAL_ROOT_UID;
19401940
stat->gid = GLOBAL_ROOT_GID;
@@ -3803,7 +3803,7 @@ static int proc_task_getattr(const struct path *path, struct kstat *stat,
38033803
{
38043804
struct inode *inode = d_inode(path->dentry);
38053805
struct task_struct *p = get_proc_task(inode);
3806-
generic_fillattr(inode, stat);
3806+
generic_fillattr(&init_user_ns, inode, stat);
38073807

38083808
if (p) {
38093809
stat->nlink += get_nr_threads(p);

fs/proc/generic.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ static int proc_getattr(const struct path *path, struct kstat *stat,
145145
}
146146
}
147147

148-
generic_fillattr(inode, stat);
148+
generic_fillattr(&init_user_ns, inode, stat);
149149
return 0;
150150
}
151151

fs/proc/proc_net.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ static int proc_tgid_net_getattr(const struct path *path, struct kstat *stat,
297297

298298
net = get_proc_task_net(inode);
299299

300-
generic_fillattr(inode, stat);
300+
generic_fillattr(&init_user_ns, inode, stat);
301301

302302
if (net != NULL) {
303303
stat->nlink = net->proc_net->nlink;

fs/proc/proc_sysctl.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ static int proc_sys_getattr(const struct path *path, struct kstat *stat,
840840
if (IS_ERR(head))
841841
return PTR_ERR(head);
842842

843-
generic_fillattr(inode, stat);
843+
generic_fillattr(&init_user_ns, inode, stat);
844844
if (table)
845845
stat->mode = (stat->mode & S_IFMT) | table->mode;
846846

fs/proc/root.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ void __init proc_root_init(void)
311311
static int proc_root_getattr(const struct path *path, struct kstat *stat,
312312
u32 request_mask, unsigned int query_flags)
313313
{
314-
generic_fillattr(d_inode(path->dentry), stat);
314+
generic_fillattr(&init_user_ns, d_inode(path->dentry), stat);
315315
stat->nlink = proc_root.nlink + nr_processes();
316316
return 0;
317317
}

fs/stat.c

+14-6
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,29 @@
2626

2727
/**
2828
* generic_fillattr - Fill in the basic attributes from the inode struct
29-
* @inode: Inode to use as the source
30-
* @stat: Where to fill in the attributes
29+
* @mnt_userns: user namespace of the mount the inode was found from
30+
* @inode: Inode to use as the source
31+
* @stat: Where to fill in the attributes
3132
*
3233
* Fill in the basic attributes in the kstat structure from data that's to be
3334
* found on the VFS inode structure. This is the default if no getattr inode
3435
* operation is supplied.
36+
*
37+
* If the inode has been found through an idmapped mount the user namespace of
38+
* the vfsmount must be passed through @mnt_userns. This function will then
39+
* take care to map the inode according to @mnt_userns before filling in the
40+
* uid and gid filds. On non-idmapped mounts or if permission checking is to be
41+
* performed on the raw inode simply passs init_user_ns.
3542
*/
36-
void generic_fillattr(struct inode *inode, struct kstat *stat)
43+
void generic_fillattr(struct user_namespace *mnt_userns, struct inode *inode,
44+
struct kstat *stat)
3745
{
3846
stat->dev = inode->i_sb->s_dev;
3947
stat->ino = inode->i_ino;
4048
stat->mode = inode->i_mode;
4149
stat->nlink = inode->i_nlink;
42-
stat->uid = inode->i_uid;
43-
stat->gid = inode->i_gid;
50+
stat->uid = i_uid_into_mnt(mnt_userns, inode);
51+
stat->gid = i_gid_into_mnt(mnt_userns, inode);
4452
stat->rdev = inode->i_rdev;
4553
stat->size = i_size_read(inode);
4654
stat->atime = inode->i_atime;
@@ -87,7 +95,7 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
8795
return inode->i_op->getattr(path, stat, request_mask,
8896
query_flags);
8997

90-
generic_fillattr(inode, stat);
98+
generic_fillattr(mnt_user_ns(path->mnt), inode, stat);
9199
return 0;
92100
}
93101
EXPORT_SYMBOL(vfs_getattr_nosec);

fs/sysv/itree.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ int sysv_getattr(const struct path *path, struct kstat *stat,
445445
u32 request_mask, unsigned int flags)
446446
{
447447
struct super_block *s = path->dentry->d_sb;
448-
generic_fillattr(d_inode(path->dentry), stat);
448+
generic_fillattr(&init_user_ns, d_inode(path->dentry), stat);
449449
stat->blocks = (s->s_blocksize / 512) * sysv_nblocks(s, stat->size);
450450
stat->blksize = s->s_blocksize;
451451
return 0;

fs/ubifs/dir.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ int ubifs_getattr(const struct path *path, struct kstat *stat,
15891589
STATX_ATTR_ENCRYPTED |
15901590
STATX_ATTR_IMMUTABLE);
15911591

1592-
generic_fillattr(inode, stat);
1592+
generic_fillattr(&init_user_ns, inode, stat);
15931593
stat->blksize = UBIFS_BLOCK_SIZE;
15941594
stat->size = ui->ui_size;
15951595

fs/udf/symlink.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ static int udf_symlink_getattr(const struct path *path, struct kstat *stat,
159159
struct inode *inode = d_backing_inode(dentry);
160160
struct page *page;
161161

162-
generic_fillattr(inode, stat);
162+
generic_fillattr(&init_user_ns, inode, stat);
163163
page = read_mapping_page(inode->i_mapping, 0, NULL);
164164
if (IS_ERR(page))
165165
return PTR_ERR(page);

fs/vboxsf/utils.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ int vboxsf_getattr(const struct path *path, struct kstat *kstat,
233233
if (err)
234234
return err;
235235

236-
generic_fillattr(d_inode(dentry), kstat);
236+
generic_fillattr(&init_user_ns, d_inode(dentry), kstat);
237237
return 0;
238238
}
239239

include/linux/fs.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -3154,7 +3154,7 @@ extern int __page_symlink(struct inode *inode, const char *symname, int len,
31543154
extern int page_symlink(struct inode *inode, const char *symname, int len);
31553155
extern const struct inode_operations page_symlink_inode_operations;
31563156
extern void kfree_link(void *);
3157-
extern void generic_fillattr(struct inode *, struct kstat *);
3157+
void generic_fillattr(struct user_namespace *, struct inode *, struct kstat *);
31583158
extern int vfs_getattr_nosec(const struct path *, struct kstat *, u32, unsigned int);
31593159
extern int vfs_getattr(const struct path *, struct kstat *, u32, unsigned int);
31603160
void __inode_add_bytes(struct inode *inode, loff_t bytes);

0 commit comments

Comments
 (0)