Commit ba5d4c15 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

cifs: fix file info setting in cifs_open_file()

In cifs_open_file(), @buf must hold a pointer to a cifs_open_info_data
structure which is passed by cifs_nt_open(), so assigning @buf
directly to @fi was obviously wrong.

Fix this by passing a valid FILE_ALL_INFO structure to SMBLegacyOpen()
and CIFS_open(), and then copy the set structure to the corresponding
cifs_open_info_data::fi field with move_cifs_info_to_smb2() helper.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=216889


Fixes: 76894f3e ("cifs: improve symlink handling for smb2+")
Signed-off-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 29cf2823
Loading
Loading
Loading
Loading
+28 −26
Original line number Diff line number Diff line
@@ -719,17 +719,25 @@ cifs_mkdir_setinfo(struct inode *inode, const char *full_path,
static int cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
			  void *buf)
{
	FILE_ALL_INFO *fi = buf;
	struct cifs_open_info_data *data = buf;
	FILE_ALL_INFO fi = {};
	int rc;

	if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS))
		return SMBLegacyOpen(xid, oparms->tcon, oparms->path,
		rc = SMBLegacyOpen(xid, oparms->tcon, oparms->path,
				   oparms->disposition,
				   oparms->desired_access,
				   oparms->create_options,
				     &oparms->fid->netfid, oplock, fi,
				   &oparms->fid->netfid, oplock, &fi,
				   oparms->cifs_sb->local_nls,
				   cifs_remap(oparms->cifs_sb));
	return CIFS_open(xid, oparms, oplock, fi);
	else
		rc = CIFS_open(xid, oparms, oplock, &fi);

	if (!rc && data)
		move_cifs_info_to_smb2(&data->fi, &fi);

	return rc;
}

static void
@@ -1053,7 +1061,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct inode *newinode = NULL;
	int rc = -EPERM;
	FILE_ALL_INFO *buf = NULL;
	struct cifs_open_info_data buf = {};
	struct cifs_io_parms io_parms;
	__u32 oplock = 0;
	struct cifs_fid fid;
@@ -1085,14 +1093,14 @@ cifs_make_node(unsigned int xid, struct inode *inode,
					    cifs_sb->local_nls,
					    cifs_remap(cifs_sb));
		if (rc)
			goto out;
			return rc;

		rc = cifs_get_inode_info_unix(&newinode, full_path,
					      inode->i_sb, xid);

		if (rc == 0)
			d_instantiate(dentry, newinode);
		goto out;
		return rc;
	}

	/*
@@ -1100,19 +1108,13 @@ cifs_make_node(unsigned int xid, struct inode *inode,
	 * support block and char device (no socket & fifo)
	 */
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
		goto out;
		return rc;

	if (!S_ISCHR(mode) && !S_ISBLK(mode))
		goto out;
		return rc;

	cifs_dbg(FYI, "sfu compat create special file\n");

	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
	if (buf == NULL) {
		rc = -ENOMEM;
		goto out;
	}

	oparms.tcon = tcon;
	oparms.cifs_sb = cifs_sb;
	oparms.desired_access = GENERIC_WRITE;
@@ -1127,21 +1129,21 @@ cifs_make_node(unsigned int xid, struct inode *inode,
		oplock = REQ_OPLOCK;
	else
		oplock = 0;
	rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf);
	rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf);
	if (rc)
		goto out;
		return rc;

	/*
	 * BB Do not bother to decode buf since no local inode yet to put
	 * timestamps in, but we can reuse it safely.
	 */

	pdev = (struct win_dev *)buf;
	pdev = (struct win_dev *)&buf.fi;
	io_parms.pid = current->tgid;
	io_parms.tcon = tcon;
	io_parms.offset = 0;
	io_parms.length = sizeof(struct win_dev);
	iov[1].iov_base = buf;
	iov[1].iov_base = &buf.fi;
	iov[1].iov_len = sizeof(struct win_dev);
	if (S_ISCHR(mode)) {
		memcpy(pdev->type, "IntxCHR", 8);
@@ -1160,8 +1162,8 @@ cifs_make_node(unsigned int xid, struct inode *inode,
	d_drop(dentry);

	/* FIXME: add code here to set EAs */
out:
	kfree(buf);

	cifs_free_open_info(&buf);
	return rc;
}