Paulo Alcantara e6259c
From: Paulo Alcantara <pc@cjr.nz>
Paulo Alcantara e6259c
Date: Fri, 6 Jan 2023 13:34:36 -0300
Paulo Alcantara e6259c
Subject: [PATCH] cifs: fix file info setting in cifs_open_file()
Paulo Alcantara e6259c
Git-commit: ba5d4c1596cada37793d405dd18d695cd3508902
Paulo Alcantara e6259c
References: git-fixes
Paulo Alcantara e6259c
Patch-mainline: v6.2-rc4
Paulo Alcantara e6259c
Paulo Alcantara e6259c
In cifs_open_file(), @buf must hold a pointer to a cifs_open_info_data
Paulo Alcantara e6259c
structure which is passed by cifs_nt_open(), so assigning @buf
Paulo Alcantara e6259c
directly to @fi was obviously wrong.
Paulo Alcantara e6259c
Paulo Alcantara e6259c
Fix this by passing a valid FILE_ALL_INFO structure to SMBLegacyOpen()
Paulo Alcantara e6259c
and CIFS_open(), and then copy the set structure to the corresponding
Paulo Alcantara e6259c
cifs_open_info_data::fi field with move_cifs_info_to_smb2() helper.
Paulo Alcantara e6259c
Paulo Alcantara e6259c
Link: https://bugzilla.kernel.org/show_bug.cgi?id=216889
Paulo Alcantara e6259c
Fixes: 76894f3e2f71 ("cifs: improve symlink handling for smb2+")
Paulo Alcantara e6259c
Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Paulo Alcantara e6259c
Signed-off-by: Steve French <stfrench@microsoft.com>
Paulo Alcantara e6259c
Acked-by: Paulo Alcantara <palcantara@suse.de>
Paulo Alcantara e6259c
---
Paulo Alcantara e6259c
 fs/cifs/smb1ops.c | 54 ++++++++++++++++++++++++-----------------------
Paulo Alcantara e6259c
 1 file changed, 28 insertions(+), 26 deletions(-)
Paulo Alcantara e6259c
Paulo Alcantara e6259c
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
Paulo Alcantara e6259c
index 5fe2c2f8ef41..4cb364454e13 100644
Paulo Alcantara e6259c
--- a/fs/cifs/smb1ops.c
Paulo Alcantara e6259c
+++ b/fs/cifs/smb1ops.c
Paulo Alcantara e6259c
@@ -719,17 +719,25 @@ cifs_mkdir_setinfo(struct inode *inode, const char *full_path,
Paulo Alcantara e6259c
 static int cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
Paulo Alcantara e6259c
 			  void *buf)
Paulo Alcantara e6259c
 {
Paulo Alcantara e6259c
-	FILE_ALL_INFO *fi = buf;
Paulo Alcantara e6259c
+	struct cifs_open_info_data *data = buf;
Paulo Alcantara e6259c
+	FILE_ALL_INFO fi = {};
Paulo Alcantara e6259c
+	int rc;
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 	if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS))
Paulo Alcantara e6259c
-		return SMBLegacyOpen(xid, oparms->tcon, oparms->path,
Paulo Alcantara e6259c
-				     oparms->disposition,
Paulo Alcantara e6259c
-				     oparms->desired_access,
Paulo Alcantara e6259c
-				     oparms->create_options,
Paulo Alcantara e6259c
-				     &oparms->fid->netfid, oplock, fi,
Paulo Alcantara e6259c
-				     oparms->cifs_sb->local_nls,
Paulo Alcantara e6259c
-				     cifs_remap(oparms->cifs_sb));
Paulo Alcantara e6259c
-	return CIFS_open(xid, oparms, oplock, fi);
Paulo Alcantara e6259c
+		rc = SMBLegacyOpen(xid, oparms->tcon, oparms->path,
Paulo Alcantara e6259c
+				   oparms->disposition,
Paulo Alcantara e6259c
+				   oparms->desired_access,
Paulo Alcantara e6259c
+				   oparms->create_options,
Paulo Alcantara e6259c
+				   &oparms->fid->netfid, oplock, &fi,
Paulo Alcantara e6259c
+				   oparms->cifs_sb->local_nls,
Paulo Alcantara e6259c
+				   cifs_remap(oparms->cifs_sb));
Paulo Alcantara e6259c
+	else
Paulo Alcantara e6259c
+		rc = CIFS_open(xid, oparms, oplock, &fi);
Paulo Alcantara e6259c
+
Paulo Alcantara e6259c
+	if (!rc && data)
Paulo Alcantara e6259c
+		move_cifs_info_to_smb2(&data->fi, &fi);
Paulo Alcantara e6259c
+
Paulo Alcantara e6259c
+	return rc;
Paulo Alcantara e6259c
 }
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 static void
Paulo Alcantara e6259c
@@ -1053,7 +1061,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
Paulo Alcantara e6259c
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
Paulo Alcantara e6259c
 	struct inode *newinode = NULL;
Paulo Alcantara e6259c
 	int rc = -EPERM;
Paulo Alcantara e6259c
-	FILE_ALL_INFO *buf = NULL;
Paulo Alcantara e6259c
+	struct cifs_open_info_data buf = {};
Paulo Alcantara e6259c
 	struct cifs_io_parms io_parms;
Paulo Alcantara e6259c
 	__u32 oplock = 0;
Paulo Alcantara e6259c
 	struct cifs_fid fid;
Paulo Alcantara e6259c
@@ -1085,14 +1093,14 @@ cifs_make_node(unsigned int xid, struct inode *inode,
Paulo Alcantara e6259c
 					    cifs_sb->local_nls,
Paulo Alcantara e6259c
 					    cifs_remap(cifs_sb));
Paulo Alcantara e6259c
 		if (rc)
Paulo Alcantara e6259c
-			goto out;
Paulo Alcantara e6259c
+			return rc;
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 		rc = cifs_get_inode_info_unix(&newinode, full_path,
Paulo Alcantara e6259c
 					      inode->i_sb, xid);
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 		if (rc == 0)
Paulo Alcantara e6259c
 			d_instantiate(dentry, newinode);
Paulo Alcantara e6259c
-		goto out;
Paulo Alcantara e6259c
+		return rc;
Paulo Alcantara e6259c
 	}
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 	/*
Paulo Alcantara e6259c
@@ -1100,19 +1108,13 @@ cifs_make_node(unsigned int xid, struct inode *inode,
Paulo Alcantara e6259c
 	 * support block and char device (no socket & fifo)
Paulo Alcantara e6259c
 	 */
Paulo Alcantara e6259c
 	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
Paulo Alcantara e6259c
-		goto out;
Paulo Alcantara e6259c
+		return rc;
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 	if (!S_ISCHR(mode) && !S_ISBLK(mode))
Paulo Alcantara e6259c
-		goto out;
Paulo Alcantara e6259c
+		return rc;
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 	cifs_dbg(FYI, "sfu compat create special file\n");
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
-	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
Paulo Alcantara e6259c
-	if (buf == NULL) {
Paulo Alcantara e6259c
-		rc = -ENOMEM;
Paulo Alcantara e6259c
-		goto out;
Paulo Alcantara e6259c
-	}
Paulo Alcantara e6259c
-
Paulo Alcantara e6259c
 	oparms.tcon = tcon;
Paulo Alcantara e6259c
 	oparms.cifs_sb = cifs_sb;
Paulo Alcantara e6259c
 	oparms.desired_access = GENERIC_WRITE;
Paulo Alcantara e6259c
@@ -1127,21 +1129,21 @@ cifs_make_node(unsigned int xid, struct inode *inode,
Paulo Alcantara e6259c
 		oplock = REQ_OPLOCK;
Paulo Alcantara e6259c
 	else
Paulo Alcantara e6259c
 		oplock = 0;
Paulo Alcantara e6259c
-	rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf);
Paulo Alcantara e6259c
+	rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf;;
Paulo Alcantara e6259c
 	if (rc)
Paulo Alcantara e6259c
-		goto out;
Paulo Alcantara e6259c
+		return rc;
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 	/*
Paulo Alcantara e6259c
 	 * BB Do not bother to decode buf since no local inode yet to put
Paulo Alcantara e6259c
 	 * timestamps in, but we can reuse it safely.
Paulo Alcantara e6259c
 	 */
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
-	pdev = (struct win_dev *)buf;
Paulo Alcantara e6259c
+	pdev = (struct win_dev *)&buf.fi;
Paulo Alcantara e6259c
 	io_parms.pid = current->tgid;
Paulo Alcantara e6259c
 	io_parms.tcon = tcon;
Paulo Alcantara e6259c
 	io_parms.offset = 0;
Paulo Alcantara e6259c
 	io_parms.length = sizeof(struct win_dev);
Paulo Alcantara e6259c
-	iov[1].iov_base = buf;
Paulo Alcantara e6259c
+	iov[1].iov_base = &buf.fi;
Paulo Alcantara e6259c
 	iov[1].iov_len = sizeof(struct win_dev);
Paulo Alcantara e6259c
 	if (S_ISCHR(mode)) {
Paulo Alcantara e6259c
 		memcpy(pdev->type, "IntxCHR", 8);
Paulo Alcantara e6259c
@@ -1160,8 +1162,8 @@ cifs_make_node(unsigned int xid, struct inode *inode,
Paulo Alcantara e6259c
 	d_drop(dentry);
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
 	/* FIXME: add code here to set EAs */
Paulo Alcantara e6259c
-out:
Paulo Alcantara e6259c
-	kfree(buf);
Paulo Alcantara e6259c
+
Paulo Alcantara e6259c
+	cifs_free_open_info(&buf;;
Paulo Alcantara e6259c
 	return rc;
Paulo Alcantara e6259c
 }
Paulo Alcantara e6259c
 
Paulo Alcantara e6259c
-- 
Paulo Alcantara e6259c
2.39.0
Paulo Alcantara e6259c
Paulo Alcantara e6259c