From: Paulo Alcantara <palcantara@suse.de>
Date: Thu, 16 Mar 2023 16:03:13 -0300
Subject: [PATCH] cifs: fix open leaks in open_cached_dir()
Patch-mainline: Never, fixed upstream by unsupported feature (ebe98f1447bb)
References: bsc#1209342
When calling open_cached_dir(), we send a compounded
SMB2_CREATE+SMB2_QUERY_INFO request when we don't have a cached root
directory handle, but if a concurrent process was able to open and
cache it (e.g. tcon->crfid.is_valid was set after unblocking from
tcon->crfid.fid_mutex), we ended up
(1) leaking open file handles as the fid assignment was done
only after tcon->crfid.is_valid check
(2) sending close requests to already-closed files due to
uninitialised fid
Fix this by moving the fid assignment up and have it set prior to
checking for concurrent opens and close extra handle accordingly.
Signed-off-by: Paulo Alcantara <palcantara@suse.de>
Acked-by: Paulo Alcantara <palcantara@suse.de>
---
fs/cifs/smb2ops.c | 40 ++++++++++++++++++----------------------
1 file changed, 18 insertions(+), 22 deletions(-)
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 90c063ff3095..016d15dab956 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -801,6 +801,22 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
rc = compound_send_recv(xid, ses, flags, 2, rqst,
resp_buftype, rsp_iov);
+ if (rc) {
+ if (rc == -EREMCHG) {
+ tcon->need_reconnect = true;
+ printk_once(KERN_WARNING "server share %s deleted\n",
+ tcon->treeName);
+ }
+ goto oshr_free;
+ }
+
+ o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
+ oparms.fid->persistent_fid = o_rsp->PersistentFileId;
+ oparms.fid->volatile_fid = o_rsp->VolatileFileId;
+#ifdef CONFIG_CIFS_DEBUG2
+ oparms.fid->mid = le64_to_cpu(o_rsp->sync_hdr.MessageId);
+#endif /* CIFS_DEBUG2 */
+
mutex_lock(&tcon->crfid.fid_mutex);
/*
@@ -825,34 +841,14 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
mutex_unlock(&tcon->crfid.fid_mutex);
- if (rc == 0) {
- /* close extra handle outside of crit sec */
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
- }
- rc = 0;
+ /* close extra handle outside of crit sec */
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
goto oshr_free;
}
/* Cached root is still invalid, continue normaly */
-
- if (rc) {
- if (rc == -EREMCHG) {
- tcon->need_reconnect = true;
- printk_once(KERN_WARNING "server share %s deleted\n",
- tcon->treeName);
- }
- goto oshr_exit;
- }
-
atomic_inc(&tcon->num_remote_opens);
- o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
- oparms.fid->persistent_fid = o_rsp->PersistentFileId;
- oparms.fid->volatile_fid = o_rsp->VolatileFileId;
-#ifdef CONFIG_CIFS_DEBUG2
- oparms.fid->mid = le64_to_cpu(o_rsp->sync_hdr.MessageId);
-#endif /* CIFS_DEBUG2 */
-
tcon->crfid.tcon = tcon;
tcon->crfid.is_valid = true;
tcon->crfid.dentry = dentry;
--
2.39.2