Commit fc20c523 authored by Meetakshi Setiya's avatar Meetakshi Setiya Committed by Steve French

cifs: fixes for get_inode_info

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: ffceb764 ("smb: client: do not defer close open handles to deleted files")
Reported-by: default avatarPaulo Alcantara <pc@manguebit.com>
Signed-off-by: default avatarMeetakshi Setiya <msetiya@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent f1b8224b
...@@ -486,7 +486,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, ...@@ -486,7 +486,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
cfile->uid = current_fsuid(); cfile->uid = current_fsuid();
cfile->dentry = dget(dentry); cfile->dentry = dget(dentry);
cfile->f_flags = file->f_flags; cfile->f_flags = file->f_flags;
cfile->status_file_deleted = false;
cfile->invalidHandle = false; cfile->invalidHandle = false;
cfile->deferred_close_scheduled = false; cfile->deferred_close_scheduled = false;
cfile->tlink = cifs_get_tlink(tlink); cfile->tlink = cifs_get_tlink(tlink);
......
...@@ -820,8 +820,10 @@ cifs_get_file_info(struct file *filp) ...@@ -820,8 +820,10 @@ cifs_get_file_info(struct file *filp)
void *page = alloc_dentry_path(); void *page = alloc_dentry_path();
const unsigned char *path; const unsigned char *path;
if (!server->ops->query_file_info) if (!server->ops->query_file_info) {
free_dentry_path(page);
return -ENOSYS; return -ENOSYS;
}
xid = get_xid(); xid = get_xid();
rc = server->ops->query_file_info(xid, tcon, cfile, &data); rc = server->ops->query_file_info(xid, tcon, cfile, &data);
...@@ -835,8 +837,8 @@ cifs_get_file_info(struct file *filp) ...@@ -835,8 +837,8 @@ cifs_get_file_info(struct file *filp)
} }
path = build_path_from_dentry(dentry, page); path = build_path_from_dentry(dentry, page);
if (IS_ERR(path)) { if (IS_ERR(path)) {
free_dentry_path(page); rc = PTR_ERR(path);
return PTR_ERR(path); goto cgfi_exit;
} }
cifs_open_info_to_fattr(&fattr, &data, inode->i_sb); cifs_open_info_to_fattr(&fattr, &data, inode->i_sb);
if (fattr.cf_flags & CIFS_FATTR_DELETE_PENDING) if (fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
...@@ -1009,7 +1011,6 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, ...@@ -1009,7 +1011,6 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
struct kvec rsp_iov, *iov = NULL; struct kvec rsp_iov, *iov = NULL;
int rsp_buftype = CIFS_NO_BUFFER; int rsp_buftype = CIFS_NO_BUFFER;
u32 tag = data->reparse.tag; u32 tag = data->reparse.tag;
struct inode *inode = NULL;
int rc = 0; int rc = 0;
if (!tag && server->ops->query_reparse_point) { if (!tag && server->ops->query_reparse_point) {
...@@ -1049,12 +1050,8 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, ...@@ -1049,12 +1050,8 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
if (tcon->posix_extensions) if (tcon->posix_extensions)
smb311_posix_info_to_fattr(fattr, data, sb); smb311_posix_info_to_fattr(fattr, data, sb);
else { else
cifs_open_info_to_fattr(fattr, data, sb); 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: out:
fattr->cf_cifstag = data->reparse.tag; fattr->cf_cifstag = data->reparse.tag;
free_rsp_buf(rsp_buftype, rsp_iov.iov_base); free_rsp_buf(rsp_buftype, rsp_iov.iov_base);
...@@ -1109,9 +1106,9 @@ static int cifs_get_fattr(struct cifs_open_info_data *data, ...@@ -1109,9 +1106,9 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
full_path, fattr); full_path, fattr);
} else { } else {
cifs_open_info_to_fattr(fattr, data, sb); 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; break;
case -EREMOTE: case -EREMOTE:
/* DFS link, no metadata available on this server */ /* DFS link, no metadata available on this server */
...@@ -1340,6 +1337,8 @@ int smb311_posix_get_inode_info(struct inode **inode, ...@@ -1340,6 +1337,8 @@ int smb311_posix_get_inode_info(struct inode **inode,
goto out; goto out;
rc = update_inode_info(sb, &fattr, inode); 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: out:
kfree(fattr.cf_symlink_target); kfree(fattr.cf_symlink_target);
return rc; return rc;
...@@ -1501,6 +1500,9 @@ struct inode *cifs_root_iget(struct super_block *sb) ...@@ -1501,6 +1500,9 @@ struct inode *cifs_root_iget(struct super_block *sb)
goto out; goto out;
} }
if (!rc && fattr.cf_flags & CIFS_FATTR_DELETE_PENDING)
cifs_mark_open_handles_for_deleted_file(inode, path);
if (rc && tcon->pipe) { if (rc && tcon->pipe) {
cifs_dbg(FYI, "ipc connection - fake read inode\n"); cifs_dbg(FYI, "ipc connection - fake read inode\n");
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment