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-23-pali@kernel.org>
Date: Sun, 31 Aug 2025 14:35:49 +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 22/35] cifs: Improve cifs_rename_pending_delete() to work without the PASSTHRU support

If PASSTHRU support is not supported by SMB server (which is currently
required for renaming the opened file) then rename the file via path before
opening it. This does not require PASSTHRU support on SMB server.

Signed-off-by: Pali Rohár <pali@...nel.org>
---
 fs/smb/client/inode.c | 63 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 50 insertions(+), 13 deletions(-)

diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index b0526787138d..9a5504a3406d 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -1711,9 +1711,13 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
 	struct tcon_link *tlink;
 	struct cifs_tcon *tcon;
 	__u32 dosattr, origattr;
+	char *sillyname_full_path = NULL;
+	bool can_rename_opened_file = true;
 	FILE_BASIC_INFO info_buf = {};
 	unsigned char sillyname[SILLYNAME_LEN + 1];
 	int sillyname_len;
+	const char *dirpath_end;
+	size_t dirpath_len;
 
 	tlink = cifs_sb_tlink(cifs_sb);
 	if (IS_ERR(tlink))
@@ -1747,13 +1751,26 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
 	}
 
 	/*
-	 * We cannot rename the file if the server doesn't support
-	 * CAP_INFOLEVEL_PASSTHRU
+	 * We cannot rename the opened file if the SMB1 server doesn't
+	 * support CAP_INFOLEVEL_PASSTHRU. But we can rename file via path.
 	 */
-	if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) {
-		rc = -EBUSY;
+	if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU))
+		can_rename_opened_file = false;
+
+	dirpath_end = strrchr(full_path, CIFS_DIR_SEP(cifs_sb));
+	if (!dirpath_end) {
+		rc = -EINVAL;
+		goto out;
+	}
+	dirpath_len = dirpath_end + 1 - full_path;
+
+	sillyname_full_path = kzalloc(dirpath_len + sillyname_len + 1, GFP_KERNEL);
+	if (!sillyname_full_path) {
+		rc = -ENOMEM;
 		goto out;
 	}
+	memcpy(sillyname_full_path, full_path, dirpath_len);
+	memcpy(sillyname_full_path + dirpath_len, sillyname, sillyname_len);
 
 	origattr = cifsInode->cifsAttrs & ~ATTR_NORMAL;
 
@@ -1784,6 +1801,16 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
 			dosattr = origattr; /* since not able to change them */
 	}
 
+	/* rename the file path (before open if server does not support renaming opened file) */
+	if (!can_rename_opened_file) {
+		rc = tcon->ses->server->ops->rename(xid, tcon, dentry, full_path,
+						    sillyname_full_path, cifs_sb);
+		if (rc != 0) {
+			rc = -EBUSY;
+			goto undo_setattr;
+		}
+	}
+
 	oparms = (struct cifs_open_parms) {
 		.tcon = tcon,
 		.cifs_sb = cifs_sb,
@@ -1796,16 +1823,18 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
 
 	rc = CIFS_open(xid, &oparms, &oplock, NULL);
 	if (rc != 0)
-		goto undo_setattr;
+		goto undo_rename_path;
 
-	/* rename the file */
-	rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, sillyname,
+	/* rename the opened file (if it was not already renamed before the open) */
+	if (can_rename_opened_file) {
+		rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, sillyname,
 				   false /* overwrite */,
 				   cifs_sb->local_nls,
 				   cifs_remap(cifs_sb));
-	if (rc != 0) {
-		rc = -EBUSY;
-		goto undo_close;
+		if (rc != 0) {
+			rc = -EBUSY;
+			goto undo_close;
+		}
 	}
 
 	/* try to set DELETE_PENDING */
@@ -1823,13 +1852,14 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
 		if (rc == -ENOENT)
 			rc = 0;
 		else if (rc != 0)
-			goto undo_rename;
+			goto undo_rename_opened_file;
 		set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
 	}
 
 	CIFSSMBClose(xid, tcon, fid.netfid);
 
 out:
+	kfree(sillyname_full_path);
 	cifs_put_tlink(tlink);
 	return rc;
 
@@ -1838,12 +1868,19 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
 	 * dealing with errors here since we can't do anything about
 	 * them anyway.
 	 */
-undo_rename:
-	CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
+undo_rename_opened_file:
+	if (can_rename_opened_file)
+		CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
 				true /* overwrite */,
 				cifs_sb->local_nls, cifs_remap(cifs_sb));
 undo_close:
 	CIFSSMBClose(xid, tcon, fid.netfid);
+undo_rename_path:
+	if (!can_rename_opened_file)
+		CIFSSMBRename(xid, tcon, dentry,
+				sillyname_full_path,
+				full_path,
+				cifs_sb);
 undo_setattr:
 	if (dosattr != origattr) {
 		info_buf.Attributes = cpu_to_le32(origattr);
-- 
2.20.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ