From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DA5EAC43331 for ; Mon, 11 Nov 2019 18:41:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AE60820674 for ; Mon, 11 Nov 2019 18:41:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1573497706; bh=f+iZtFf6D0uzo11UKz1/ulbPHU3sfWmtgQoGfZNO8lc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=VBC+c/QupC30PCzv1WvQenyGbgBb5YwnKgLMAbd0NOgnNCUSBSJ+O2Rqrx3T/IAFA cvo3tfNIRN4lRDpa4iSdDFxUz38kNhHJmqY4L6tsI59YQFQgAa75jQCnM3vrG3W/J+ f/XxgxHBLQZT25cy1VM4xv2q6q/LjSn0sGJM9QGk= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729436AbfKKSlp (ORCPT ); Mon, 11 Nov 2019 13:41:45 -0500 Received: from mail.kernel.org ([198.145.29.99]:32846 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729418AbfKKSlo (ORCPT ); Mon, 11 Nov 2019 13:41:44 -0500 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id AE6D420659; Mon, 11 Nov 2019 18:41:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1573497703; bh=f+iZtFf6D0uzo11UKz1/ulbPHU3sfWmtgQoGfZNO8lc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qsc3xFs9NX1K8D20bFFhMa94Gu6+yAEkhmATLS4gQqtacqXeR++qM0sZ4lJ4qRFE5 MAlhzA5V7FQqxRcYx/yAeSEhwtV9+WNTzxKkhNMjnul7KsCgT+vMcvQRm809VRKjO7 mTswlRDmh9se/HJq7+4xzCdZQyiSdZqMRWP+J1uU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Luis Henriques , Jeff Layton , Ilya Dryomov Subject: [PATCH 4.19 031/125] ceph: fix use-after-free in __ceph_remove_cap() Date: Mon, 11 Nov 2019 19:27:50 +0100 Message-Id: <20191111181444.911553332@linuxfoundation.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191111181438.945353076@linuxfoundation.org> References: <20191111181438.945353076@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Luis Henriques commit ea60ed6fcf29eebc78f2ce91491e6309ee005a01 upstream. KASAN reports a use-after-free when running xfstest generic/531, with the following trace: [ 293.903362] kasan_report+0xe/0x20 [ 293.903365] rb_erase+0x1f/0x790 [ 293.903370] __ceph_remove_cap+0x201/0x370 [ 293.903375] __ceph_remove_caps+0x4b/0x70 [ 293.903380] ceph_evict_inode+0x4e/0x360 [ 293.903386] evict+0x169/0x290 [ 293.903390] __dentry_kill+0x16f/0x250 [ 293.903394] dput+0x1c6/0x440 [ 293.903398] __fput+0x184/0x330 [ 293.903404] task_work_run+0xb9/0xe0 [ 293.903410] exit_to_usermode_loop+0xd3/0xe0 [ 293.903413] do_syscall_64+0x1a0/0x1c0 [ 293.903417] entry_SYSCALL_64_after_hwframe+0x44/0xa9 This happens because __ceph_remove_cap() may queue a cap release (__ceph_queue_cap_release) which can be scheduled before that cap is removed from the inode list with rb_erase(&cap->ci_node, &ci->i_caps); And, when this finally happens, the use-after-free will occur. This can be fixed by removing the cap from the inode list before being removed from the session list, and thus eliminating the risk of an UAF. Cc: stable@vger.kernel.org Signed-off-by: Luis Henriques Reviewed-by: Jeff Layton Signed-off-by: Ilya Dryomov Signed-off-by: Greg Kroah-Hartman --- fs/ceph/caps.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1053,6 +1053,11 @@ void __ceph_remove_cap(struct ceph_cap * dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode); + /* remove from inode's cap rbtree, and clear auth cap */ + rb_erase(&cap->ci_node, &ci->i_caps); + if (ci->i_auth_cap == cap) + ci->i_auth_cap = NULL; + /* remove from session list */ spin_lock(&session->s_cap_lock); if (session->s_cap_iterator == cap) { @@ -1088,11 +1093,6 @@ void __ceph_remove_cap(struct ceph_cap * spin_unlock(&session->s_cap_lock); - /* remove from inode list */ - rb_erase(&cap->ci_node, &ci->i_caps); - if (ci->i_auth_cap == cap) - ci->i_auth_cap = NULL; - if (removed) ceph_put_cap(mdsc, cap);