lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ