Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp1200154pxa; Thu, 20 Aug 2020 05:28:35 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy3HB8SJQxKog+zStrTG3nlw6ilBZ0sweYNzFFgWAN/WW4D/NsvI3yHmOqkP84jINsmoCLM X-Received: by 2002:a17:906:3e06:: with SMTP id k6mr1220119eji.37.1597926515558; Thu, 20 Aug 2020 05:28:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1597926515; cv=none; d=google.com; s=arc-20160816; b=FifGy3hCI42qA2M8sXGk/jPKvo2jSF9aAIMTiWcLKgKZkcrmtKVCtZYagnd7v8quol qDMdN+7fEJOXn9lkXT+KvZ2ifaScwkCb5rEbUBEA0FmU4LfPWCeDUIrPGszhxO5nv8nX +lfztArU7a6fRuYDfrehRFxXNtJHl1Lb8pC55HJcC73SHj6uCMuDV6z16d14olH1n34T V8BUVmvHjf6ZwcjJ1m/eeo/F4XYuk9KND0GFDOhwSn0J7foVGKcwMjXZby4NMF0Gvpow YJDwMy+DYsM3s4ijkqRAUWZOgoQlD6MSOOtFhHvaSENSYGWVQo8W2WhQfBjlykiHeFb9 ml3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Jo3GrnTch0JCb8O5jZkhOghukCwoKxrp1yWZvRwnwq8=; b=ggJWmYyO3cZjpdOlnfVpc1g2hv7KcO4EAE/MytIhTUtBwSdmXBYuNZgNRpfKCFHbyZ juoNFAUsX8CO7RQeSC0/8rIDH24xxOzv02oKdhCGhZNwtSL2WbiRNBvFrdifA5Taykj1 GVzqafLpTecz+bbeJQn9+O7oLaAy7f5CtXvMiwlAiiFAYp+cQEcv2Wjj7MGmBsYVsXNu 60SLIrBXclnJjO5n9Zc6gN3j6t4HGTpkrcYJ/cx9CjhNyXqIa8o46PhNO6wt3pHCSX+C eh32DWvEXdSwEiWShTooSfT67OSer7A0uroLQUd1pD7StX6EzTsw5oQ39xC/zrc0SjQe deFw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=iBDt00H9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e16si1417798ejl.531.2020.08.20.05.28.11; Thu, 20 Aug 2020 05:28:35 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=iBDt00H9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729427AbgHTJwh (ORCPT + 99 others); Thu, 20 Aug 2020 05:52:37 -0400 Received: from mail.kernel.org ([198.145.29.99]:33774 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729623AbgHTJw2 (ORCPT ); Thu, 20 Aug 2020 05:52:28 -0400 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 2F75E20855; Thu, 20 Aug 2020 09:52:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1597917147; bh=Bmg10UqZE2OfqzUwO5/985U5PYWvxAjDL4ixoSb1H2c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iBDt00H9lnaKcS3kpfTFnO/GZk2Pds8gxU60cZ6zw0Deai819VpHV2XKdqj8F3OXm S9Z0YawjbDra0/VPjODs/2TOXdL9GzdW9LnV94Yg03EkTpQwVmuCQ0NXv/LJRlI4g5 PbI8exx8YGOWIw99FDjllk2BW9lLw8nCgWd/do8I= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Paul Aurich , Aurelien Aptel , Steve French Subject: [PATCH 4.19 21/92] cifs: Fix leak when handling lease break for cached root fid Date: Thu, 20 Aug 2020 11:21:06 +0200 Message-Id: <20200820091538.665967126@linuxfoundation.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200820091537.490965042@linuxfoundation.org> References: <20200820091537.490965042@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: Paul Aurich commit baf57b56d3604880ccb3956ec6c62ea894f5de99 upstream. Handling a lease break for the cached root didn't free the smb2_lease_break_work allocation, resulting in a leak: unreferenced object 0xffff98383a5af480 (size 128): comm "cifsd", pid 684, jiffies 4294936606 (age 534.868s) hex dump (first 32 bytes): c0 ff ff ff 1f 00 00 00 88 f4 5a 3a 38 98 ff ff ..........Z:8... 88 f4 5a 3a 38 98 ff ff 80 88 d6 8a ff ff ff ff ..Z:8........... backtrace: [<0000000068957336>] smb2_is_valid_oplock_break+0x1fa/0x8c0 [<0000000073b70b9e>] cifs_demultiplex_thread+0x73d/0xcc0 [<00000000905fa372>] kthread+0x11c/0x150 [<0000000079378e4e>] ret_from_fork+0x22/0x30 Avoid this leak by only allocating when necessary. Fixes: a93864d93977 ("cifs: add lease tracking to the cached root fid") Signed-off-by: Paul Aurich CC: Stable # v4.18+ Reviewed-by: Aurelien Aptel Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/cifs/smb2misc.c | 73 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 21 deletions(-) --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -509,15 +509,31 @@ cifs_ses_oplock_break(struct work_struct kfree(lw); } +static void +smb2_queue_pending_open_break(struct tcon_link *tlink, __u8 *lease_key, + __le32 new_lease_state) +{ + struct smb2_lease_break_work *lw; + + lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL); + if (!lw) { + cifs_put_tlink(tlink); + return; + } + + INIT_WORK(&lw->lease_break, cifs_ses_oplock_break); + lw->tlink = tlink; + lw->lease_state = new_lease_state; + memcpy(lw->lease_key, lease_key, SMB2_LEASE_KEY_SIZE); + queue_work(cifsiod_wq, &lw->lease_break); +} + static bool -smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp, - struct smb2_lease_break_work *lw) +smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp) { - bool found; __u8 lease_state; struct list_head *tmp; struct cifsFileInfo *cfile; - struct cifs_pending_open *open; struct cifsInodeInfo *cinode; int ack_req = le32_to_cpu(rsp->Flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); @@ -556,22 +572,29 @@ smb2_tcon_has_lease(struct cifs_tcon *tc &cinode->flags); cifs_queue_oplock_break(cfile); - kfree(lw); return true; } - found = false; + return false; +} + +static struct cifs_pending_open * +smb2_tcon_find_pending_open_lease(struct cifs_tcon *tcon, + struct smb2_lease_break *rsp) +{ + __u8 lease_state = le32_to_cpu(rsp->NewLeaseState); + int ack_req = le32_to_cpu(rsp->Flags & + SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); + struct cifs_pending_open *open; + struct cifs_pending_open *found = NULL; + list_for_each_entry(open, &tcon->pending_opens, olist) { if (memcmp(open->lease_key, rsp->LeaseKey, SMB2_LEASE_KEY_SIZE)) continue; if (!found && ack_req) { - found = true; - memcpy(lw->lease_key, open->lease_key, - SMB2_LEASE_KEY_SIZE); - lw->tlink = cifs_get_tlink(open->tlink); - queue_work(cifsiod_wq, &lw->lease_break); + found = open; } cifs_dbg(FYI, "found in the pending open list\n"); @@ -592,14 +615,7 @@ smb2_is_valid_lease_break(char *buffer) struct TCP_Server_Info *server; struct cifs_ses *ses; struct cifs_tcon *tcon; - struct smb2_lease_break_work *lw; - - lw = kmalloc(sizeof(struct smb2_lease_break_work), GFP_KERNEL); - if (!lw) - return false; - - INIT_WORK(&lw->lease_break, cifs_ses_oplock_break); - lw->lease_state = rsp->NewLeaseState; + struct cifs_pending_open *open; cifs_dbg(FYI, "Checking for lease break\n"); @@ -617,11 +633,27 @@ smb2_is_valid_lease_break(char *buffer) spin_lock(&tcon->open_file_lock); cifs_stats_inc( &tcon->stats.cifs_stats.num_oplock_brks); - if (smb2_tcon_has_lease(tcon, rsp, lw)) { + if (smb2_tcon_has_lease(tcon, rsp)) { spin_unlock(&tcon->open_file_lock); spin_unlock(&cifs_tcp_ses_lock); return true; } + open = smb2_tcon_find_pending_open_lease(tcon, + rsp); + if (open) { + __u8 lease_key[SMB2_LEASE_KEY_SIZE]; + struct tcon_link *tlink; + + tlink = cifs_get_tlink(open->tlink); + memcpy(lease_key, open->lease_key, + SMB2_LEASE_KEY_SIZE); + spin_unlock(&tcon->open_file_lock); + spin_unlock(&cifs_tcp_ses_lock); + smb2_queue_pending_open_break(tlink, + lease_key, + rsp->NewLeaseState); + return true; + } spin_unlock(&tcon->open_file_lock); if (tcon->crfid.is_valid && @@ -639,7 +671,6 @@ smb2_is_valid_lease_break(char *buffer) } } spin_unlock(&cifs_tcp_ses_lock); - kfree(lw); cifs_dbg(FYI, "Can not process lease break - no lease matched\n"); return false; }