From: Miklos Szeredi <mszeredi(a)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(a)9livesdata.com>
Signed-off-by: Miklos Szeredi <mszeredi(a)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(a)huawei.com>
Reviewed-by: Zhang Yi <yi.zhang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)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) {
--
2.25.1