From nobody Wed Oct 8 00:45:56 2025 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8C2F2C148; Thu, 3 Jul 2025 13:27:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751549244; cv=none; b=Bj9nenL5cq0iSi11LCNuKF12PeOpmtnRX+BU5AdPpbm9mRZW1rIy/1q7ALdtSQn+4KChFNCaoYC7qBHtnk7q5MM3C37CJuu3zBGczkJwHJGKFbVOeA0riGjkj6oQrWjqiiu0ibnYKxhGFAQr16St067HejlLbqAiZWaakzYhURw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751549244; c=relaxed/simple; bh=h9Lj1Kr+0dRjXxXHU3VKmCLHLTiQTtjJXR5BpFXLhq8=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=gQdH8Fz2Afl47ykpPf++vnBmLkGOSNU1c1T67yk/8/+KrxDn5hjtEYTpxUA2MegrwYgamzR3QjbkVH41u+7OWbAUo5UUjPgNyZGHr0HCyNstw9Ag2TLX7x6hhl3s7a7F+f/YjPFwjqqW+/OmJFmeVLw0tYJ4l24T+NJ5w+jmQeA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.216]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4bXyHD1PSYzKHLxK; Thu, 3 Jul 2025 21:27:20 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.252]) by mail.maildlp.com (Postfix) with ESMTP id 980F81A14CD; Thu, 3 Jul 2025 21:27:18 +0800 (CST) Received: from huaweicloud.com (unknown [10.175.104.67]) by APP3 (Coremail) with SMTP id _Ch0CgA3mSYzhWZoVG4eAg--.12632S4; Thu, 03 Jul 2025 21:27:17 +0800 (CST) From: Wang Zhaolong To: sfrench@samba.org, pshilov@microsoft.com, aaptel@suse.com Cc: linux-cifs@vger.kernel.org, samba-technical@lists.samba.org, linux-kernel@vger.kernel.org, chengzhihao1@huawei.com, wangzhaolong1@huawei.com, yi.zhang@huawei.com, yangerkun@huawei.com Subject: [PATCH] smb: client: fix use-after-free in cifs_oplock_break Date: Thu, 3 Jul 2025 21:20:02 +0800 Message-Id: <20250703132002.627709-1-wangzhaolong@huaweicloud.com> X-Mailer: git-send-email 2.39.2 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _Ch0CgA3mSYzhWZoVG4eAg--.12632S4 X-Coremail-Antispam: 1UD129KBjvJXoWxAF4kGF4kuFy5uFW5JFyxXwb_yoW5CFWUpF 13Kr15Wr45GryUuwsaqF4ru3W3t3WkWa1F9ry8Ww1Sy343J3ySgF4rKr129F4SqFWkAr1q gF4jg3yqvF1UArJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUv2b4IE77IF4wAFF20E14v26r4j6ryUM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6r1F6r1fM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4 vEj48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Ar0_tr1l84ACjcxK6xIIjxv20xvEc7Cj xVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x 0267AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG 6I80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFV Cjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0E n4kS14v26r1q6r43MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I 0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWU tVW8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcV CY1x0267AKxVWUJVW8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAF wI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa 7IU17KsUUUUUU== X-CM-SenderInfo: pzdqw6xkdrz0tqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" A race condition can occur in cifs_oplock_break() leading to a use-after-free of the cinode structure when unmounting: cifs_oplock_break() spin_lock(&cinode->open_file_lock) <- OK _cifsFileInfo_put(cfile) cifsFileInfo_put_final() cifs_sb_deactive() [last ref, start releasing sb] kill_sb() kill_anon_super() generic_shutdown_super() evict_inodes() dispose_list() evict() destroy_inode() call_rcu(&inode->i_rcu, i_callback) [later] i_callback() cifs_free_inode() kmem_cache_free(cinode) spin_unlock(&cinode->open_file_lock) <- UAF cifs_done_oplock_break(cinode) <- UAF The issue occurs when umount has already released its reference to the superblock. When _cifsFileInfo_put() calls cifs_sb_deactive(), this releases the last reference, triggering the immediate cleanup of all inodes under RCU. However, cifs_oplock_break() continues to access the cinode after this point, resulting in use-after-free. Fix this by holding an extra reference to the superblock during the entire oplock break operation. This ensures that the superblock and its inodes remain valid until the oplock break completes. Link: https://bugzilla.kernel.org/show_bug.cgi?id=3D220309 Fixes: b98749cac4a6 ("CIFS: keep FileInfo handle live during oplock break") Signed-off-by: Wang Zhaolong --- fs/smb/client/file.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index e9212da32f01..1421bde045c2 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -3086,20 +3086,27 @@ bool is_size_safe_to_change(struct cifsInodeInfo *c= ifsInode, __u64 end_of_file, void cifs_oplock_break(struct work_struct *work) { struct cifsFileInfo *cfile =3D container_of(work, struct cifsFileInfo, oplock_break); struct inode *inode =3D d_inode(cfile->dentry); - struct cifs_sb_info *cifs_sb =3D CIFS_SB(inode->i_sb); + struct super_block *sb =3D inode->i_sb; + struct cifs_sb_info *cifs_sb =3D CIFS_SB(sb); struct cifsInodeInfo *cinode =3D CIFS_I(inode); struct cifs_tcon *tcon; struct TCP_Server_Info *server; struct tcon_link *tlink; int rc =3D 0; bool purge_cache =3D false, oplock_break_cancelled; __u64 persistent_fid, volatile_fid; __u16 net_fid; =20 + /* + * Hold a reference to the superblock to prevent it and its inodes from + * being freed while we are accessing cinode. Otherwise, _cifsFileInfo_pu= t() + * may release the last reference to the sb and trigger inode eviction. + */ + cifs_sb_active(sb); wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS, TASK_UNINTERRUPTIBLE); =20 tlink =3D cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) @@ -3168,10 +3175,11 @@ void cifs_oplock_break(struct work_struct *work) spin_unlock(&cinode->open_file_lock); =20 cifs_put_tlink(tlink); out: cifs_done_oplock_break(cinode); + cifs_sb_deactive(sb); } =20 static int cifs_swap_activate(struct swap_info_struct *sis, struct file *swap_file, sector_t *span) { --=20 2.39.2