Commit 1e9ea8ed authored by Jeff Layton's avatar Jeff Layton Committed by Zizhi Wo
Browse files

ceph: fix auth cap handling logic in remove_session_caps_cb

mainline inclusion
from mainline-v5.16-rc1
commit 3c305026
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/?id=3c3050267e3c9a230f23a5621d7c6bd084d15094



--------------------------------

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: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>

Conflicts:
	fs/ceph/mds_client.c
[Adaptation context]
Signed-off-by: default avatarZizhi Wo <wozizhi@huawei.com>
parent 2f738d2d
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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) {