cifs: fixes for get_inode_info
authorMeetakshi Setiya <msetiya@microsoft.com>
Thu, 14 Mar 2024 12:05:49 +0000 (08:05 -0400)
committerSteve French <stfrench@microsoft.com>
Thu, 14 Mar 2024 18:54:27 +0000 (13:54 -0500)
Fix potential memory leaks, add error checking, remove unnecessary
initialisation of status_file_deleted and do not use cifs_iget() to get
inode in reparse_info_to_fattr since fattrs may not be fully set.

Fixes: ffceb7640cbf ("smb: client: do not defer close open handles to deleted files")
Reported-by: Paulo Alcantara <pc@manguebit.com>
Signed-off-by: Meetakshi Setiya <msetiya@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/file.c
fs/smb/client/inode.c

index e7d5e8f..16aadce 100644 (file)
@@ -486,7 +486,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        cfile->uid = current_fsuid();
        cfile->dentry = dget(dentry);
        cfile->f_flags = file->f_flags;
-       cfile->status_file_deleted = false;
        cfile->invalidHandle = false;
        cfile->deferred_close_scheduled = false;
        cfile->tlink = cifs_get_tlink(tlink);
index 8177ec5..6092729 100644 (file)
@@ -820,8 +820,10 @@ cifs_get_file_info(struct file *filp)
        void *page = alloc_dentry_path();
        const unsigned char *path;
 
-       if (!server->ops->query_file_info)
+       if (!server->ops->query_file_info) {
+               free_dentry_path(page);
                return -ENOSYS;
+       }
 
        xid = get_xid();
        rc = server->ops->query_file_info(xid, tcon, cfile, &data);
@@ -835,8 +837,8 @@ cifs_get_file_info(struct file *filp)
                }
                path = build_path_from_dentry(dentry, page);
                if (IS_ERR(path)) {
-                       free_dentry_path(page);
-                       return PTR_ERR(path);
+                       rc = PTR_ERR(path);
+                       goto cgfi_exit;
                }
                cifs_open_info_to_fattr(&fattr, &data, inode->i_sb);
                if (fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
@@ -1009,7 +1011,6 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
        struct kvec rsp_iov, *iov = NULL;
        int rsp_buftype = CIFS_NO_BUFFER;
        u32 tag = data->reparse.tag;
-       struct inode *inode = NULL;
        int rc = 0;
 
        if (!tag && server->ops->query_reparse_point) {
@@ -1049,12 +1050,8 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
 
        if (tcon->posix_extensions)
                smb311_posix_info_to_fattr(fattr, data, sb);
-       else {
+       else
                cifs_open_info_to_fattr(fattr, data, sb);
-               inode = cifs_iget(sb, fattr);
-               if (inode && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
-                       cifs_mark_open_handles_for_deleted_file(inode, full_path);
-       }
 out:
        fattr->cf_cifstag = data->reparse.tag;
        free_rsp_buf(rsp_buftype, rsp_iov.iov_base);
@@ -1109,9 +1106,9 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
                                                   full_path, fattr);
                } else {
                        cifs_open_info_to_fattr(fattr, data, sb);
-                       if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
-                               cifs_mark_open_handles_for_deleted_file(*inode, full_path);
                }
+               if (!rc && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
+                       cifs_mark_open_handles_for_deleted_file(*inode, full_path);
                break;
        case -EREMOTE:
                /* DFS link, no metadata available on this server */
@@ -1340,6 +1337,8 @@ int smb311_posix_get_inode_info(struct inode **inode,
                goto out;
 
        rc = update_inode_info(sb, &fattr, inode);
+       if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
+               cifs_mark_open_handles_for_deleted_file(*inode, full_path);
 out:
        kfree(fattr.cf_symlink_target);
        return rc;
@@ -1501,6 +1500,9 @@ iget_root:
                goto out;
        }
 
+       if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
+               cifs_mark_open_handles_for_deleted_file(inode, path);
+
        if (rc && tcon->pipe) {
                cifs_dbg(FYI, "ipc connection - fake read inode\n");
                spin_lock(&inode->i_lock);