On 9/21/23 07:48, Christian Brauner wrote:
Imho, this is all very wild but I'm not judging.
Two solutions imho:
(1) teach stacking filesystems like overlayfs and ecryptfs to use
vfs_getattr_nosec() in their ->getattr() implementation when they
are themselves called via vfs_getattr_nosec(). This will fix this by
not triggering another LSM hook.
This somewhat lengthy patch I think would be a solution for (1). I don't
think the Fixes tag is correct but IMO it should propagate farther back,
if possible.
From 01467f6e879c4cd757abb4d79cb18bf11150bed8 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@xxxxxxxxxxxxx>
Date: Thu, 28 Sep 2023 14:42:39 -0400
Subject: [PATCH] fs: Enable GETATTR_NOSEC parameter for getattr interface
function
When vfs_getattr_nosec() calls a filesystem's getattr interface function
then the 'nosec' should propagate into this function so that
vfs_getattr_nosec() can again be called from the filesystem's gettattr
rather than vfs_getattr(). The latter would add unnecessary security
checks that the initial vfs_getattr_nosec() call wanted to avoid.
Therefore, introduce the getattr flag GETATTR_NOSEC and allow to pass
with the new getattr_flags parameter to the getattr interface function.
In overlayfs and ecryptfs use this flag to determine which one of the
two functions to call.
In a recent code change introduced to IMA vfs_getattr_nosec() ended up
calling vfs_getattr() in overlayfs, which in turn called
security_inode_getattr() on an exiting process that did not have
current->fs set anymore, which then caused a kernel NULL pointer
dereference. With this change the call to security_inode_getattr() can
be avoided, thus avoiding the NULL pointer dereference.
Reported-by: syzbot+a67fc5321ffb4b311c98@xxxxxxxxxxxxxxxxxxxxxxxxx
Fixes: db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx>
---
simple_getattr has been adjusted and all files returned by the following
grep have been adjusted as well.
grep -rEI "^[[:space:]]+\.getattr" ./ | \
grep -v simple_getattr | \
cut -d ":" -f1 | sort | uniq
---
fs/9p/vfs_inode.c | 3 ++-
fs/9p/vfs_inode_dotl.c | 3 ++-
fs/afs/inode.c | 3 ++-
fs/afs/internal.h | 2 +-
fs/bad_inode.c | 3 ++-
fs/btrfs/inode.c | 3 ++-
fs/ceph/inode.c | 9 ++++++---
fs/ceph/super.h | 3 ++-
fs/coda/coda_linux.h | 2 +-
fs/coda/inode.c | 3 ++-
fs/ecryptfs/inode.c | 14 ++++++++++----
fs/erofs/inode.c | 2 +-
fs/erofs/internal.h | 2 +-
fs/exfat/exfat_fs.h | 2 +-
fs/exfat/file.c | 2 +-
fs/ext2/ext2.h | 2 +-
fs/ext2/inode.c | 3 ++-
fs/ext4/ext4.h | 6 ++++--
fs/ext4/inode.c | 9 ++++++---
fs/ext4/symlink.c | 6 ++++--
fs/f2fs/f2fs.h | 3 ++-
fs/f2fs/file.c | 3 ++-
fs/f2fs/namei.c | 6 ++++--
fs/fat/fat.h | 3 ++-
fs/fat/file.c | 3 ++-
fs/fuse/dir.c | 3 ++-
fs/gfs2/inode.c | 4 +++-
fs/hfsplus/hfsplus_fs.h | 2 +-
fs/hfsplus/inode.c | 2 +-
fs/kernfs/inode.c | 3 ++-
fs/kernfs/kernfs-internal.h | 3 ++-
fs/libfs.c | 5 +++--
fs/minix/inode.c | 3 ++-
fs/minix/minix.h | 3 ++-
fs/nfs/inode.c | 3 ++-
fs/nfs/namespace.c | 5 +++--
fs/ntfs3/file.c | 3 ++-
fs/ntfs3/ntfs_fs.h | 3 ++-
fs/ocfs2/file.c | 3 ++-
fs/ocfs2/file.h | 3 ++-
fs/orangefs/inode.c | 3 ++-
fs/orangefs/orangefs-kernel.h | 3 ++-
fs/overlayfs/inode.c | 8 ++++++--
fs/overlayfs/overlayfs.h | 3 ++-
fs/proc/base.c | 6 ++++--
fs/proc/fd.c | 3 ++-
fs/proc/generic.c | 3 ++-
fs/proc/internal.h | 3 ++-
fs/proc/proc_net.c | 3 ++-
fs/proc/proc_sysctl.c | 3 ++-
fs/proc/root.c | 3 ++-
fs/smb/client/cifsfs.h | 3 ++-
fs/smb/client/inode.c | 3 ++-
fs/stat.c | 3 ++-
fs/sysv/itree.c | 3 ++-
fs/sysv/sysv.h | 2 +-
fs/ubifs/dir.c | 3 ++-
fs/ubifs/file.c | 6 ++++--
fs/ubifs/ubifs.h | 3 ++-
fs/udf/symlink.c | 3 ++-
fs/vboxsf/utils.c | 3 ++-
fs/vboxsf/vfsmod.h | 2 +-
fs/xfs/xfs_iops.c | 3 ++-
include/linux/fs.h | 10 ++++++++--
include/linux/nfs_fs.h | 2 +-
mm/shmem.c | 3 ++-
66 files changed, 159 insertions(+), 82 deletions(-)
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 0d28ecf668d0..9c5a7e653bb1 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1000,7 +1000,8 @@ v9fs_vfs_rename(struct mnt_idmap *idmap, struct
inode *old_dir,
static int
v9fs_vfs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct dentry *dentry = path->dentry;
struct inode *inode = d_inode(dentry);
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 1312f68965ac..e4238ee243bf 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -439,7 +439,8 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
static int
v9fs_vfs_getattr_dotl(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags)
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct dentry *dentry = path->dentry;
struct v9fs_session_info *v9ses;
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 1c794a1896aa..8763e6126a8c 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -750,7 +750,8 @@ int afs_validate(struct afs_vnode *vnode, struct key
*key)
* read the attributes of an inode
*/
int afs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int query_flags)
+ struct kstat *stat, u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct afs_vnode *vnode = AFS_FS_I(inode);
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index da73b97e19a9..b8dfb6232086 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1175,7 +1175,7 @@ extern bool afs_check_validity(struct afs_vnode *);
extern int afs_validate(struct afs_vnode *, struct key *);
bool afs_pagecache_valid(struct afs_vnode *);
extern int afs_getattr(struct mnt_idmap *idmap, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int, unsigned int);
extern int afs_setattr(struct mnt_idmap *idmap, struct dentry *,
struct iattr *);
extern void afs_evict_inode(struct inode *);
extern int afs_drop_inode(struct inode *);
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 83f9566c973b..22219161382d 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -97,7 +97,8 @@ static int bad_inode_permission(struct mnt_idmap *idmap,
static int bad_inode_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
return -EIO;
}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7814b9d654ce..bc9fbaa42b93 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8624,7 +8624,8 @@ int __init btrfs_init_cachep(void)
static int btrfs_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags)
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
u64 delalloc_bytes;
u64 inode_bytes;
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 800ab7920513..a798f0a7238f 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2255,11 +2255,13 @@ static const char
*ceph_encrypted_get_link(struct dentry *dentry,
static int ceph_encrypted_symlink_getattr(struct mnt_idmap *idmap,
const struct path *path,
struct kstat *stat, u32 request_mask,
- unsigned int query_flags)
+ unsigned int query_flags,
+ unsigned int getattr_flags)
{
int ret;
- ret = ceph_getattr(idmap, path, stat, request_mask, query_flags);
+ ret = ceph_getattr(idmap, path, stat, request_mask, query_flags,
+ getattr_flags);
if (ret)
return ret;
return fscrypt_symlink_getattr(path, stat);
@@ -2960,7 +2962,8 @@ static int statx_to_caps(u32 want, umode_t mode)
* then we can avoid talking to the MDS at all.
*/
int ceph_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct super_block *sb = inode->i_sb;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 51c7f2b14f6f..f472cefd21bd 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1100,7 +1100,8 @@ extern int ceph_setattr(struct mnt_idmap *idmap,
struct dentry *dentry, struct iattr *attr);
extern int ceph_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags);
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags);
void ceph_inode_shutdown(struct inode *inode);
static inline bool ceph_inode_is_shutdown(struct inode *inode)
diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h
index dd6277d87afb..ec6e30cbb35f 100644
--- a/fs/coda/coda_linux.h
+++ b/fs/coda/coda_linux.h
@@ -50,7 +50,7 @@ int coda_permission(struct mnt_idmap *idmap, struct
inode *inode,
int mask);
int coda_revalidate_inode(struct inode *);
int coda_getattr(struct mnt_idmap *, const struct path *, struct kstat *,
- u32, unsigned int);
+ u32, unsigned int, unsigned int);
int coda_setattr(struct mnt_idmap *, struct dentry *, struct iattr *);
/* this file: helpers */
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 0c7c2528791e..52465963c455 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -252,7 +252,8 @@ static void coda_evict_inode(struct inode *inode)
}
int coda_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
int err = coda_revalidate_inode(d_inode(path->dentry));
if (!err)
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 992d9c7e64ae..31173a4534d2 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -974,7 +974,8 @@ static int ecryptfs_setattr(struct mnt_idmap *idmap,
static int ecryptfs_getattr_link(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags)
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct dentry *dentry = path->dentry;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
@@ -1000,14 +1001,19 @@ static int ecryptfs_getattr_link(struct
mnt_idmap *idmap,
static int ecryptfs_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags)
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct dentry *dentry = path->dentry;
struct kstat lower_stat;
int rc;
- rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat,
- request_mask, flags);
+ if (getattr_flags & GETATTR_NOSEC)
+ rc = vfs_getattr_nosec(ecryptfs_dentry_to_lower_path(dentry),
+ &lower_stat, request_mask, flags);
+ else
+ rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry),
+ &lower_stat, request_mask, flags);
if (!rc) {
fsstack_copy_attr_all(d_inode(dentry),
ecryptfs_inode_to_lower(d_inode(dentry)));
diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c
index edc8ec7581b8..f9ac4c001c17 100644
--- a/fs/erofs/inode.c
+++ b/fs/erofs/inode.c
@@ -358,7 +358,7 @@ struct inode *erofs_iget(struct super_block *sb,
erofs_nid_t nid)
int erofs_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask,
- unsigned int query_flags)
+ unsigned int query_flags, unsigned int getattr_flags)
{
struct inode *const inode = d_inode(path->dentry);
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 4ff88d0dd980..16fbb39d670f 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -422,7 +422,7 @@ int erofs_map_blocks(struct inode *inode, struct
erofs_map_blocks *map);
struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid);
int erofs_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask,
- unsigned int query_flags);
+ unsigned int query_flags, unsigned int getattr_flags);
int erofs_namei(struct inode *dir, const struct qstr *name,
erofs_nid_t *nid, unsigned int *d_type);
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index f55498e5c23d..5e86c62de12f 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -454,7 +454,7 @@ int exfat_setattr(struct mnt_idmap *idmap, struct
dentry *dentry,
struct iattr *attr);
int exfat_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, unsigned int request_mask,
- unsigned int query_flags);
+ unsigned int query_flags, unsigned int getattr_flags);
int exfat_file_fsync(struct file *file, loff_t start, loff_t end, int
datasync);
long exfat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
long exfat_compat_ioctl(struct file *filp, unsigned int cmd,
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index 32395ef686a2..06cb318bfa0a 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -227,7 +227,7 @@ void exfat_truncate(struct inode *inode)
int exfat_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, unsigned int request_mask,
- unsigned int query_flags)
+ unsigned int query_flags, unsigned int getattr_flags)
{
struct inode *inode = d_backing_inode(path->dentry);
struct exfat_inode_info *ei = EXFAT_I(inode);
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 7fdd685c384d..a2b460786d21 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -748,7 +748,7 @@ void ext2_write_failed(struct address_space
*mapping, loff_t to);
extern int ext2_get_block(struct inode *, sector_t, struct buffer_head
*, int);
extern int ext2_setattr (struct mnt_idmap *, struct dentry *, struct
iattr *);
extern int ext2_getattr (struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int, unsigned int);
extern void ext2_set_inode_flags(struct inode *inode);
extern int ext2_fiemap(struct inode *inode, struct fiemap_extent_info
*fieinfo,
u64 start, u64 len);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 314b415ee518..153738e254ac 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -1611,7 +1611,8 @@ int ext2_write_inode(struct inode *inode, struct
writeback_control *wbc)
}
int ext2_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int query_flags)
+ struct kstat *stat, u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct ext2_inode_info *ei = EXT2_I(inode);
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 9418359b1d9d..90b1e08bd89a 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2977,11 +2977,13 @@ extern int ext4_setattr(struct mnt_idmap *,
struct dentry *,
struct iattr *);
extern u32 ext4_dio_alignment(struct inode *inode);
extern int ext4_getattr(struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int,
+ unsigned int);
extern void ext4_evict_inode(struct inode *);
extern void ext4_clear_inode(struct inode *);
extern int ext4_file_getattr(struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int,
+ unsigned int);
extern void ext4_dirty_inode(struct inode *, int);
extern int ext4_change_inode_journal_flag(struct inode *, int);
extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 4ce35f1c8b0a..ede71d313519 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5515,7 +5515,8 @@ u32 ext4_dio_alignment(struct inode *inode)
}
int ext4_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int query_flags)
+ struct kstat *stat, u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct ext4_inode *raw_inode;
@@ -5577,12 +5578,14 @@ int ext4_getattr(struct mnt_idmap *idmap, const
struct path *path,
int ext4_file_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
u64 delalloc_blocks;
- ext4_getattr(idmap, path, stat, request_mask, query_flags);
+ ext4_getattr(idmap, path, stat, request_mask, query_flags,
+ getattr_flags);
/*
* If there is inline data in the inode, the inode will normally not
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index 75bf1f88843c..abc30ebb2be2 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -58,9 +58,11 @@ static const char *ext4_encrypted_get_link(struct
dentry *dentry,
static int ext4_encrypted_symlink_getattr(struct mnt_idmap *idmap,
const struct path *path,
struct kstat *stat, u32 request_mask,
- unsigned int query_flags)
+ unsigned int query_flags,
+ unsigned int getattr_flags)
{
- ext4_getattr(idmap, path, stat, request_mask, query_flags);
+ ext4_getattr(idmap, path, stat, request_mask, query_flags,
+ getattr_flags);
return fscrypt_symlink_getattr(path, stat);
}
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 6d688e42d89c..0a8436cd2f5f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3477,7 +3477,8 @@ int f2fs_do_truncate_blocks(struct inode *inode,
u64 from, bool lock);
int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock);
int f2fs_truncate(struct inode *inode);
int f2fs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags);
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags);
int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr);
int f2fs_truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t
pg_end);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index ca5904129b16..e05bdd318aef 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -832,7 +832,8 @@ static bool f2fs_force_buffered_io(struct inode
*inode, int rw)
}
int f2fs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int query_flags)
+ struct kstat *stat, u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct f2fs_inode_info *fi = F2FS_I(inode);
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 193b22a2d6bf..cfdcdeb2c0b0 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -1356,9 +1356,11 @@ static const char *f2fs_encrypted_get_link(struct
dentry *dentry,
static int f2fs_encrypted_symlink_getattr(struct mnt_idmap *idmap,
const struct path *path,
struct kstat *stat, u32 request_mask,
- unsigned int query_flags)
+ unsigned int query_flags,
+ unsigned int getattr_flags)
{
- f2fs_getattr(idmap, path, stat, request_mask, query_flags);
+ f2fs_getattr(idmap, path, stat, request_mask, query_flags,
+ getattr_flags);
return fscrypt_symlink_getattr(path, stat);
}
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 66cf4778cf3b..74b57f2e1c36 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -403,7 +403,8 @@ extern int fat_setattr(struct mnt_idmap *idmap,
struct dentry *dentry,
extern void fat_truncate_blocks(struct inode *inode, loff_t offset);
extern int fat_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags);
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags);
extern int fat_file_fsync(struct file *file, loff_t start, loff_t end,
int datasync);
diff --git a/fs/fat/file.c b/fs/fat/file.c
index e887e9ab7472..2177784f54a2 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -396,7 +396,8 @@ void fat_truncate_blocks(struct inode *inode, loff_t
offset)
}
int fat_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index d707e6987da9..3531d4239635 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -2069,7 +2069,8 @@ static int fuse_setattr(struct mnt_idmap *idmap,
struct dentry *entry,
static int fuse_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags)
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct fuse_conn *fc = get_fuse_conn(inode);
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 0eac04507904..50383ec30573 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2038,6 +2038,7 @@ static int gfs2_setattr(struct mnt_idmap *idmap,
* @stat: The inode's stats
* @request_mask: Mask of STATX_xxx flags indicating the caller's
interests
* @flags: AT_STATX_xxx setting
+ * @getattr_flags: GETATTR_xxx
*
* This may be called from the VFS directly, or from within GFS2 with the
* inode locked, so we look to see if the glock is already locked and only
@@ -2050,7 +2051,8 @@ static int gfs2_setattr(struct mnt_idmap *idmap,
static int gfs2_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags)
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct gfs2_inode *ip = GFS2_I(inode);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 7ededcb720c1..3da3a79c9742 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -483,7 +483,7 @@ int hfsplus_cat_read_inode(struct inode *inode,
struct hfs_find_data *fd);
int hfsplus_cat_write_inode(struct inode *inode);
int hfsplus_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask,
- unsigned int query_flags);
+ unsigned int query_flags, unsigned int getattr_flags);
int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
int datasync);
int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index c65c8c4b03dd..afa7e8ee8cb2 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -278,7 +278,7 @@ static int hfsplus_setattr(struct mnt_idmap *idmap,
int hfsplus_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask,
- unsigned int query_flags)
+ unsigned int query_flags, unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 922719a343a7..92af4b394274 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -182,7 +182,8 @@ static void kernfs_refresh_inode(struct kernfs_node
*kn, struct inode *inode)
int kernfs_iop_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct kernfs_node *kn = inode->i_private;
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index a9b854cdfdb5..ccf74e08105c 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -135,7 +135,8 @@ int kernfs_iop_setattr(struct mnt_idmap *idmap,
struct dentry *dentry,
struct iattr *iattr);
int kernfs_iop_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags);
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags);
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t
size);
int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr);
diff --git a/fs/libfs.c b/fs/libfs.c
index 37f2d34ee090..757d24b8f4be 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -30,7 +30,7 @@
int simple_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask,
- unsigned int query_flags)
+ unsigned int query_flags, unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
@@ -1579,7 +1579,8 @@ static struct dentry *empty_dir_lookup(struct
inode *dir, struct dentry *dentry,
static int empty_dir_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index df575473c1cc..74ae2c33f5a5 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -651,7 +651,8 @@ static int minix_write_inode(struct inode *inode,
struct writeback_control *wbc)
}
int minix_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct super_block *sb = path->dentry->d_sb;
struct inode *inode = d_inode(path->dentry);
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index d493507c064f..6ac55d3b649c 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -52,7 +52,8 @@ extern int minix_new_block(struct inode * inode);
extern void minix_free_block(struct inode *inode, unsigned long block);
extern unsigned long minix_count_free_blocks(struct super_block *sb);
extern int minix_getattr(struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int,
+ unsigned int);
extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned
len);
extern void V1_minix_truncate(struct inode *);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index e21c073158e5..c5cad2515b37 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -831,7 +831,8 @@ static u32 nfs_get_valid_attrmask(struct inode *inode)
}
int nfs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int query_flags)
+ struct kstat *stat, u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct nfs_server *server = NFS_SERVER(inode);
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index e7494cdd957e..d4c3622ff4ed 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -210,11 +210,12 @@ struct vfsmount *nfs_d_automount(struct path *path)
static int
nfs_namespace_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
if (NFS_FH(d_inode(path->dentry))->size != 0)
return nfs_getattr(idmap, path, stat, request_mask,
- query_flags);
+ query_flags, getattr_flags);
generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(path->dentry),
stat);
return 0;
diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c
index 962f12ce6c0a..729ca3c09958 100644
--- a/fs/ntfs3/file.c
+++ b/fs/ntfs3/file.c
@@ -72,7 +72,8 @@ static long ntfs_compat_ioctl(struct file *filp, u32
cmd, unsigned long arg)
* ntfs_getattr - inode_operations::getattr
*/
int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, u32 flags)
+ struct kstat *stat, u32 request_mask, u32 flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct ntfs_inode *ni = ntfs_i(inode);
diff --git a/fs/ntfs3/ntfs_fs.h b/fs/ntfs3/ntfs_fs.h
index 629403ede6e5..3c83352883f2 100644
--- a/fs/ntfs3/ntfs_fs.h
+++ b/fs/ntfs3/ntfs_fs.h
@@ -492,7 +492,8 @@ extern const struct file_operations ntfs_dir_operations;
/* Globals from file.c */
int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, u32 flags);
+ struct kstat *stat, u32 request_mask, u32 flags,
+ unsigned int getattr_flags);
int ntfs3_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr);
void ntfs_sparse_cluster(struct inode *inode, struct page *page0, CLST
vcn,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index c45596c25c66..7e367cd801d3 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1300,7 +1300,8 @@ int ocfs2_setattr(struct mnt_idmap *idmap, struct
dentry *dentry,
}
int ocfs2_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct super_block *sb = path->dentry->d_sb;
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 8e53e4ac1120..2dbf4edd94da 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -52,7 +52,8 @@ int ocfs2_zero_extend(struct inode *inode, struct
buffer_head *di_bh,
int ocfs2_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr);
int ocfs2_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags);
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags);
int ocfs2_permission(struct mnt_idmap *idmap,
struct inode *inode,
int mask);
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 085912268442..f7c2c318d392 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -859,7 +859,8 @@ int orangefs_setattr(struct mnt_idmap *idmap, struct
dentry *dentry,
* Obtain attributes of an object given a dentry
*/
int orangefs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
int ret;
struct inode *inode = path->dentry->d_inode;
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index b711654ca18a..f0682b51e5e0 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -365,7 +365,8 @@ int __orangefs_setattr_mode(struct dentry *dentry,
struct iattr *iattr);
int orangefs_setattr(struct mnt_idmap *, struct dentry *, struct iattr *);
int orangefs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags);
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags);
int orangefs_permission(struct mnt_idmap *idmap,
struct inode *inode, int mask);
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 83ef66644c21..8c0f3e125d09 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -155,7 +155,8 @@ static void ovl_map_dev_ino(struct dentry *dentry,
struct kstat *stat, int fsid)
}
int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct dentry *dentry = path->dentry;
enum ovl_path_type type;
@@ -171,7 +172,10 @@ int ovl_getattr(struct mnt_idmap *idmap, const
struct path *path,
type = ovl_path_real(dentry, &realpath);
old_cred = ovl_override_creds(dentry->d_sb);
- err = vfs_getattr(&realpath, stat, request_mask, flags);
+ if (getattr_flags & GETATTR_NOSEC)
+ err = vfs_getattr_nosec(&realpath, stat, request_mask, flags);
+ else
+ err = vfs_getattr(&realpath, stat, request_mask, flags);
if (err)
goto out;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 9817b2dcb132..6f91bfb1bbbd 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -687,7 +687,8 @@ unsigned int ovl_get_nlink(struct ovl_fs *ofs,
struct dentry *lowerdentry,
int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr);
int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags);
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags);
int ovl_permission(struct mnt_idmap *idmap, struct inode *inode,
int mask);
int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const
char *name,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ffd54617c354..3e733cd17fba 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1960,7 +1960,8 @@ static struct inode
*proc_pid_make_base_inode(struct super_block *sb,
}
int pid_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int query_flags)
+ struct kstat *stat, u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
@@ -3896,7 +3897,8 @@ static int proc_task_readdir(struct file *file,
struct dir_context *ctx)
static int proc_task_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct task_struct *p = get_proc_task(inode);
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 6276b3938842..1ea9eea9953d 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -347,7 +347,8 @@ int proc_fd_permission(struct mnt_idmap *idmap,
static int proc_fd_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
int rv = 0;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 775ce0bcf08c..4acb07536329 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -135,7 +135,8 @@ static int proc_notify_change(struct mnt_idmap *idmap,
static int proc_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct proc_dir_entry *de = PDE(inode);
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 9a8f32f21ff5..c3bc8eee4771 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -163,7 +163,8 @@ extern int proc_pid_statm(struct seq_file *, struct
pid_namespace *,
*/
extern const struct dentry_operations pid_dentry_operations;
extern int pid_getattr(struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int,
+ unsigned int);
extern int proc_setattr(struct mnt_idmap *, struct dentry *,
struct iattr *);
extern void proc_pid_evict_inode(struct proc_inode *);
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 2ba31b6d68c0..e76019d1fe3b 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -301,7 +301,8 @@ static struct dentry *proc_tgid_net_lookup(struct
inode *dir,
static int proc_tgid_net_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct net *net;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index c88854df0b62..3dc86f02f64e 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -842,7 +842,8 @@ static int proc_sys_setattr(struct mnt_idmap *idmap,
static int proc_sys_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct ctl_table_header *head = grab_header(inode);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 9191248f2dac..ab9113fc119d 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -312,7 +312,8 @@ void __init proc_root_init(void)
static int proc_root_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(path->dentry),
stat);
diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h
index 41daebd220ff..453a3bd7ba65 100644
--- a/fs/smb/client/cifsfs.h
+++ b/fs/smb/client/cifsfs.h
@@ -73,7 +73,8 @@ extern int cifs_invalidate_mapping(struct inode *inode);
extern int cifs_revalidate_mapping(struct inode *inode);
extern int cifs_zap_mapping(struct inode *inode);
extern int cifs_getattr(struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int,
+ unsigned int);
extern int cifs_setattr(struct mnt_idmap *, struct dentry *,
struct iattr *);
extern int cifs_fiemap(struct inode *, struct fiemap_extent_info *,
u64 start,
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index d7c302442c1e..1aa1bd0c85fd 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -2570,7 +2570,8 @@ int cifs_revalidate_dentry(struct dentry *dentry)
}
int cifs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct dentry *dentry = path->dentry;
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
diff --git a/fs/stat.c b/fs/stat.c
index d43a5cc1bfa4..fc4f6c0a91a8 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -133,7 +133,8 @@ int vfs_getattr_nosec(const struct path *path,
struct kstat *stat,
idmap = mnt_idmap(path->mnt);
if (inode->i_op->getattr)
return inode->i_op->getattr(idmap, path, stat,
- request_mask, query_flags);
+ request_mask, query_flags,
+ GETATTR_NOSEC);
generic_fillattr(idmap, request_mask, inode, stat);
return 0;
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index edb94e55de8e..3ff96577f0db 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -446,7 +446,8 @@ static unsigned sysv_nblocks(struct super_block *s,
loff_t size)
}
int sysv_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct super_block *s = path->dentry->d_sb;
generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(path->dentry),
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index e3f988b469ee..1e6e1e2faad4 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -142,7 +142,7 @@ extern int sysv_write_inode(struct inode *, struct
writeback_control *wbc);
extern int sysv_sync_inode(struct inode *);
extern void sysv_set_inode(struct inode *, dev_t);
extern int sysv_getattr(struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int, unsigned int);
extern int sysv_init_icache(void);
extern void sysv_destroy_icache(void);
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 2f48c58d47cd..30fe9f64292c 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1632,7 +1632,8 @@ static int ubifs_rename(struct mnt_idmap *idmap,
}
int ubifs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags)
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
loff_t size;
struct inode *inode = d_inode(path->dentry);
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index e5382f0b2587..ef0dda82adfc 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1622,9 +1622,11 @@ static const char *ubifs_get_link(struct dentry
*dentry,
static int ubifs_symlink_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
- ubifs_getattr(idmap, path, stat, request_mask, query_flags);
+ ubifs_getattr(idmap, path, stat, request_mask, query_flags,
+ getattr_flags);
if (IS_ENCRYPTED(d_inode(path->dentry)))
return fscrypt_symlink_getattr(path, stat);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index ebb3ad6b5e7e..bf1429096176 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -2033,7 +2033,8 @@ int ubifs_update_time(struct inode *inode, int flags);
struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
umode_t mode, bool is_xattr);
int ubifs_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *stat, u32 request_mask, unsigned int flags);
+ struct kstat *stat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags);
int ubifs_check_dir_empty(struct inode *dir);
/* xattr.c */
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index f7eaf7b14594..743f5f59e94c 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -143,7 +143,8 @@ static int udf_symlink_filler(struct file *file,
struct folio *folio)
static int udf_symlink_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int flags)
+ u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
struct dentry *dentry = path->dentry;
struct inode *inode = d_backing_inode(dentry);
diff --git a/fs/vboxsf/utils.c b/fs/vboxsf/utils.c
index 83f20dd15522..8bbc31c99ede 100644
--- a/fs/vboxsf/utils.c
+++ b/fs/vboxsf/utils.c
@@ -232,7 +232,8 @@ int vboxsf_inode_revalidate(struct dentry *dentry)
}
int vboxsf_getattr(struct mnt_idmap *idmap, const struct path *path,
- struct kstat *kstat, u32 request_mask, unsigned int flags)
+ struct kstat *kstat, u32 request_mask, unsigned int flags,
+ unsigned int getattr_flags)
{
int err;
struct dentry *dentry = path->dentry;
diff --git a/fs/vboxsf/vfsmod.h b/fs/vboxsf/vfsmod.h
index 05973eb89d52..8ec1edc0cbe6 100644
--- a/fs/vboxsf/vfsmod.h
+++ b/fs/vboxsf/vfsmod.h
@@ -99,7 +99,7 @@ int vboxsf_stat_dentry(struct dentry *dentry, struct
shfl_fsobjinfo *info);
int vboxsf_inode_revalidate(struct dentry *dentry);
int vboxsf_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *kstat, u32 request_mask,
- unsigned int query_flags);
+ unsigned int query_flags, unsigned int getattr_flags);
int vboxsf_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *iattr);
struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 1c1e6171209d..d70ab9d791a9 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -552,7 +552,8 @@ xfs_vn_getattr(
const struct path *path,
struct kstat *stat,
u32 request_mask,
- unsigned int query_flags)
+ unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = d_inode(path->dentry);
struct xfs_inode *ip = XFS_I(inode);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b528f063e8ff..f2ec5a48e5dc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1924,7 +1924,7 @@ struct inode_operations {
struct inode *, struct dentry *, unsigned int);
int (*setattr) (struct mnt_idmap *, struct dentry *, struct iattr *);
int (*getattr) (struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int, unsigned int);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
u64 len);
@@ -2098,6 +2098,11 @@ static inline bool sb_rdonly(const struct
super_block *sb) { return sb->s_flags
#define IS_WHITEOUT(inode) (S_ISCHR(inode->i_mode) && \
(inode)->i_rdev == WHITEOUT_DEV)
+/*
+ * getattr flags
+ */
+#define GETATTR_NOSEC (1 << 0)
+
static inline bool HAS_UNMAPPED_ID(struct mnt_idmap *idmap,
struct inode *inode)
{
@@ -3066,7 +3071,8 @@ extern int dcache_readdir(struct file *, struct
dir_context *);
extern int simple_setattr(struct mnt_idmap *, struct dentry *,
struct iattr *);
extern int simple_getattr(struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int,
+ unsigned int);
extern int simple_statfs(struct dentry *, struct kstatfs *);
extern int simple_open(struct inode *inode, struct file *file);
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 279262057a92..f6cecdbe11ca 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -421,7 +421,7 @@ extern int nfs_post_op_update_inode(struct inode
*inode, struct nfs_fattr *fattr
extern int nfs_post_op_update_inode_force_wcc(struct inode *inode,
struct nfs_fattr *fattr);
extern int nfs_post_op_update_inode_force_wcc_locked(struct inode
*inode, struct nfs_fattr *fattr);
extern int nfs_getattr(struct mnt_idmap *, const struct path *,
- struct kstat *, u32, unsigned int);
+ struct kstat *, u32, unsigned int, unsigned int);
extern void nfs_access_add_cache(struct inode *, struct
nfs_access_entry *, const struct cred *);
extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
extern int nfs_permission(struct mnt_idmap *, struct inode *, int);
diff --git a/mm/shmem.c b/mm/shmem.c
index 69595d341882..ff43a0d248bb 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1119,7 +1119,8 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
static int shmem_getattr(struct mnt_idmap *idmap,
const struct path *path, struct kstat *stat,
- u32 request_mask, unsigned int query_flags)
+ u32 request_mask, unsigned int query_flags,
+ unsigned int getattr_flags)
{
struct inode *inode = path->dentry->d_inode;
struct shmem_inode_info *info = SHMEM_I(inode);
--
2.40.1