[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250831123602.14037-36-pali@kernel.org>
Date: Sun, 31 Aug 2025 14:36:02 +0200
From: Pali Rohár <pali@...nel.org>
To: Steve French <sfrench@...ba.org>,
Paulo Alcantara <pc@...guebit.com>,
ronnie sahlberg <ronniesahlberg@...il.com>
Cc: linux-cifs@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH 35/35] cifs: Use CREATE_OPTION_EXCLUSIVE when doing SMB1 rmdir on NT server
Windows NT servers just set the DELETE_PENDING flag when executing the SMB1
SMB_COM_DELETE_DIRECTORY command. This is opposite of the SMB_COM_DELETE
command (can be used only on files) which completely removes the file and
not just transition it into DELETE_PENDING state.
This means that the SMB1 rmdir against Windows NT servers has same issues
as SMB2+ rmdir and silly rename needs to be used. As in SMB2+ rmdir, use
the CREATE_OPTION_EXCLUSIVE logic for issuing SMB1 rmdir when communicating
with NT-based SMB1 server.
With this change Linux rmdir() syscall called on SMB1 mounts from Windows
NT servers cause that on success the path would not exist anymore and new
file or directory with that path can be created.
Signed-off-by: Pali Rohár <pali@...nel.org>
---
fs/smb/client/cifssmb.c | 45 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index 37bc0541bc21..31638b71ee0c 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -823,8 +823,53 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
int bytes_returned;
int name_len;
int remap = cifs_remap(cifs_sb);
+ struct cifs_open_parms oparms;
+ struct cifs_fid fid;
+ int oplock;
cifs_dbg(FYI, "In CIFSSMBRmDir\n");
+
+ /*
+ * Do not send SMB_COM_DELETE_DIRECTORY to NT servers. NT servers just
+ * sets the DELETE PENDING state on the directory and in case that
+ * directory is opened by some other client, it stay in this state and
+ * direntry stay present in the parent directory.
+ *
+ * So for NT servers use NT OPEN in exclusive mode. It fails when some
+ * other SMB client has the directory opened, and it triggers the
+ * sillyrename code path. After successful NT OPEN in exclusive mode,
+ * sets the DELETE PENDING state and close the directory.
+ *
+ * Servers with UNIX extensions should support SMB_COM_DELETE_DIRECTORY
+ * with correct UNIX semantics, so use this NT OPEN + DELETE PENDING
+ * only against non-UNIX NT servers.
+ */
+ if ((tcon->ses->capabilities & CAP_NT_SMBS) &&
+ !(cap_unix(tcon->ses) &&
+ (le64_to_cpu(tcon->fsUnixInfo.Capability) & CIFS_UNIX_POSIX_PATH_OPS_CAP))) {
+ oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE, FILE_OPEN,
+ CREATE_OPTION_EXCLUSIVE | CREATE_NOT_FILE | OPEN_REPARSE_POINT,
+ ACL_NO_MODE);
+ oparms.fid = &fid;
+ oplock = 0;
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc)
+ return rc;
+ rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid, current->tgid);
+ /*
+ * some samba versions return -ENOENT when we try to set the
+ * file disposition here. Likely a samba bug, but work around
+ * it for now. This means that some cifsXXX files may hang
+ * around after they shouldn't.
+ *
+ * BB: remove this hack after more servers have the fix
+ */
+ if (rc == -ENOENT)
+ rc = 0;
+ CIFSSMBClose(xid, tcon, fid.netfid);
+ return rc;
+ }
+
RmDirRetry:
rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
(void **) &pSMBr);
--
2.20.1
Powered by blists - more mailing lists