From: Jeff Layton jlayton@kernel.org
mainline inclusion from mainline-v5.16-rc1 commit 3c3050267e3c9a230f23a5621d7c6bd084d15094 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9R4KH CVE: CVE-2023-52732
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
The existing logic relies on ci->i_auth_cap being NULL, but if we end up removing the auth cap early, then we'll do a lot of useless work and lock-taking on the remaining caps. Ensure that we only do the auth cap removal when we're _actually_ removing the auth cap.
Signed-off-by: Jeff Layton jlayton@kernel.org Signed-off-by: Ilya Dryomov idryomov@gmail.com
Conflicts: fs/ceph/mds_client.c [Adaptation context] Signed-off-by: Zizhi Wo wozizhi@huawei.com --- fs/ceph/mds_client.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index c7c6cde3faaa..d5f86f4e90d2 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1640,6 +1640,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, struct ceph_fs_client *fsc = (struct ceph_fs_client *)arg; struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_inode_info *ci = ceph_inode(inode); + bool is_auth; bool dirty_dropped = false; bool invalidate = false; int capsnap_release = 0; @@ -1647,8 +1648,9 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, dout("removing cap %p, ci is %p, inode is %p\n", cap, ci, &ci->vfs_inode); spin_lock(&ci->i_ceph_lock); + is_auth = (cap == ci->i_auth_cap); __ceph_remove_cap(cap, false); - if (!ci->i_auth_cap) { + if (is_auth) { struct ceph_cap_flush *cf;
if (READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {