ceph: correctly handle releasing an embedded cap flush
authorXiubo Li <xiubli@redhat.com>
Wed, 18 Aug 2021 13:38:42 +0000 (21:38 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 3 Sep 2021 08:09:22 +0000 (10:09 +0200)
commite55a8b461585a77ad3c42e6ae1fdad9efb0ff207
treee6086c65880166712adef5eb62af72c3848ee33f
parent7008b9981b6ab6150075891b433b2b2d426618a7
ceph: correctly handle releasing an embedded cap flush

commit b2f9fa1f3bd8846f50b355fc2168236975c4d264 upstream.

The ceph_cap_flush structures are usually dynamically allocated, but
the ceph_cap_snap has an embedded one.

When force umounting, the client will try to remove all the session
caps. During this, it will free them, but that should not be done
with the ones embedded in a capsnap.

Fix this by adding a new boolean that indicates that the cap flush is
embedded in a capsnap, and skip freeing it if that's set.

At the same time, switch to using list_del_init() when detaching the
i_list and g_list heads.  It's possible for a forced umount to remove
these objects but then handle_cap_flushsnap_ack() races in and does the
list_del_init() again, corrupting memory.

Cc: stable@vger.kernel.org
URL: https://tracker.ceph.com/issues/52283
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ceph/caps.c
fs/ceph/mds_client.c
fs/ceph/snap.c
fs/ceph/super.h