cifs: fix file info setting in cifs_open_file()
authorPaulo Alcantara <pc@cjr.nz>
Fri, 6 Jan 2023 16:34:36 +0000 (13:34 -0300)
committerSteve French <stfrench@microsoft.com>
Mon, 9 Jan 2023 19:47:02 +0000 (13:47 -0600)
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: 76894f3e2f71 ("cifs: improve symlink handling for smb2+")
Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/smb1ops.c

index 5fe2c2f..4cb3644 100644 (file)
@@ -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,
-                                    oparms->disposition,
-                                    oparms->desired_access,
-                                    oparms->create_options,
-                                    &oparms->fid->netfid, oplock, fi,
-                                    oparms->cifs_sb->local_nls,
-                                    cifs_remap(oparms->cifs_sb));
-       return CIFS_open(xid, oparms, oplock, fi);
+               rc = SMBLegacyOpen(xid, oparms->tcon, oparms->path,
+                                  oparms->disposition,
+                                  oparms->desired_access,
+                                  oparms->create_options,
+                                  &oparms->fid->netfid, oplock, &fi,
+                                  oparms->cifs_sb->local_nls,
+                                  cifs_remap(oparms->cifs_sb));
+       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;
 }