From: Miklos Szeredi mszeredi@redhat.com
mainline inclusion from mainline-v5.8-rc1 commit 5ddd9ced9aef6cfa76af27d384c17c9e2d610ce8 category: bugfix bugzilla: 37636 CVE: NA
-------------------------------------------------
A GETATTR request can race with FUSE_NOTIFY_INVAL_INODE, resulting in the attribute cache being updated with stale information after the invalidation.
Fix this by bumping the attribute version in fuse_reverse_inval_inode().
Reported-by: Krzysztof Rusek rusek@9livesdata.com Signed-off-by: Miklos Szeredi mszeredi@redhat.com
Conflict: fs/fuse/inode.c a. commit f15ecfef058d ("fuse: Introduce fi->lock to protect write related fields") is not backported, 'fi->lock' do not exist. b. commit 4510d86fbbb3 ("fuse: Convert fc->attr_version into atomic64_t") is not backported, 'fc->lock' is needed to read 'fc->attr_version'. Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/fuse/inode.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 821597c618843..e245e0d405046 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -334,6 +334,8 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, loff_t offset, loff_t len) { + struct fuse_conn *fc = get_fuse_conn_super(sb); + struct fuse_inode *fi; struct inode *inode; pgoff_t pg_start; pgoff_t pg_end; @@ -342,6 +344,11 @@ int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, if (!inode) return -ENOENT;
+ fi = get_fuse_inode(inode); + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; + spin_unlock(&fc->lock); + fuse_invalidate_attr(inode); forget_all_cached_acls(inode); if (offset >= 0) {